mirror of
https://github.com/opencv/opencv.git
synced 2026-07-22 03:43:03 +04:00
Compare commits
1287 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b0dc474160 | |||
| adf89bbb33 | |||
| 583bd1a6e2 | |||
| 53eda42da7 | |||
| c26c4a61c6 | |||
| 65fcf22670 | |||
| d0572538ff | |||
| 3577265508 | |||
| 1a24e316d5 | |||
| 9da9e8244b | |||
| 8d51ef0f35 | |||
| 9cfae823a7 | |||
| d6151eae23 | |||
| 4a0a3281c6 | |||
| 1230075011 | |||
| 7459954377 | |||
| cf38098ba8 | |||
| 8ca394efaf | |||
| f9c7931800 | |||
| 24547f40ff | |||
| 72debee125 | |||
| 08c270f65a | |||
| e585453c2e | |||
| 86f4524010 | |||
| 6d098cc230 | |||
| 434c96e625 | |||
| d6e9616256 | |||
| e9187ae38c | |||
| 978dc76653 | |||
| b409fd32ac | |||
| a2ad997e97 | |||
| e9428726ca | |||
| 400906b433 | |||
| 50d7c61c01 | |||
| d9bf522b27 | |||
| 93dc0679ec | |||
| 1ddc51cfd1 | |||
| 50bf0e10f5 | |||
| d1ccb7e47f | |||
| 7e845a3b87 | |||
| ea1c970190 | |||
| 3d207ccf11 | |||
| aaf7f5ae02 | |||
| 50e8ad285b | |||
| bb5462e327 | |||
| df2e7fa6eb | |||
| 11f36bdf9a | |||
| bc0d4585b3 | |||
| 70917f291c | |||
| 9f6f0c7424 | |||
| 4722a8df3c | |||
| 7be8a71c60 | |||
| ce859edba8 | |||
| 90820cd044 | |||
| c929f1b62f | |||
| ff88132620 | |||
| 89f8d4ae12 | |||
| 3f4ffe7844 | |||
| ed567a2dd1 | |||
| 22a00036e2 | |||
| 2aac0a5a26 | |||
| 07ad6a437e | |||
| d9a444ca1a | |||
| 766f58ed7e | |||
| 1099b4c881 | |||
| 7c0f49fc36 | |||
| 761e796201 | |||
| 8d0fbc6a1e | |||
| affcea8822 | |||
| 53f0be00a9 | |||
| 602caa9cd6 | |||
| f35ec8c955 | |||
| 1316491e50 | |||
| 2cc4309bf8 | |||
| 612d43f284 | |||
| 56824d1769 | |||
| 2238ac7d59 | |||
| 2b5b192cd7 | |||
| 64e1d23cba | |||
| 40d2904f3d | |||
| 9712cc479b | |||
| 0ef1fb0b67 | |||
| 2b67bc448d | |||
| a3f81b79ed | |||
| 8d0dae4cec | |||
| dda96264df | |||
| 4af8e5c5c4 | |||
| eff5605be5 | |||
| 2b53ab23c0 | |||
| 2010de9104 | |||
| 280a99b3b6 | |||
| 646025589b | |||
| 4502003e61 | |||
| 07abb6240e | |||
| dea0815199 | |||
| e4ed2d2e42 | |||
| c8228e5789 | |||
| 667e5e4f89 | |||
| ada703a73a | |||
| 9e1e960116 | |||
| 82ae9ef541 | |||
| 1b07274e34 | |||
| 15ac54d5d6 | |||
| 1cdd8510fd | |||
| 039f3d01a0 | |||
| f63feea05e | |||
| fbac38d98b | |||
| ca2ab3387f | |||
| 64ded50bbf | |||
| d44ac61033 | |||
| 18ada77d8a | |||
| 6d0f1275c2 | |||
| a848eccfc6 | |||
| 2402fa4824 | |||
| 2bf4135afc | |||
| c677f132cd | |||
| ec4015d73c | |||
| 8c42dbf71c | |||
| 4ca679180d | |||
| 64da959619 | |||
| 88123e2512 | |||
| 87e98e8788 | |||
| 767857c516 | |||
| 2b60166e5c | |||
| 2e41db39f5 | |||
| a55fa8389e | |||
| d23142027f | |||
| 438fe3f9db | |||
| 5cc154147f | |||
| 9cd5a0a1e6 | |||
| 2958142e31 | |||
| 27c15bed60 | |||
| 2985739b8c | |||
| 2465d93330 | |||
| 556d211136 | |||
| 0ee2a58cdc | |||
| 7daf84fb44 | |||
| 9aff01c9a9 | |||
| a2b84e9897 | |||
| 66f3c2673c | |||
| 554d08c3a1 | |||
| 3a595ea5c4 | |||
| 03c9648f2e | |||
| e3a55af336 | |||
| be4a432bea | |||
| 0d32a24cba | |||
| e36948cfbc | |||
| 9aa647068b | |||
| 092030c1ca | |||
| 0bd261ded4 | |||
| 7ed557497d | |||
| d793ec2ffe | |||
| 271f7df343 | |||
| 08d44f588f | |||
| 84b4a5a495 | |||
| b2e20a82ba | |||
| 1b3a06a02a | |||
| 91a5e75151 | |||
| 4754b0e253 | |||
| 84b517f5a0 | |||
| 8ac88cf069 | |||
| 13a995cc1d | |||
| a93fb52632 | |||
| 4d927e73f1 | |||
| 38228709c8 | |||
| 38788a3161 | |||
| 46b6973c05 | |||
| af2b7708a8 | |||
| a233982931 | |||
| ed1439fbc6 | |||
| b379b67a32 | |||
| f3945fbddb | |||
| 8b44ee2ce1 | |||
| 7b582b71ba | |||
| 4e8c507276 | |||
| 9390c56831 | |||
| abebbf04b1 | |||
| 5e434073d4 | |||
| 3e4a566e46 | |||
| 6f5cf8c15f | |||
| b687bc807a | |||
| 5440fd6cb4 | |||
| b060151625 | |||
| be38d4ea93 | |||
| 56f21c4fd5 | |||
| 386df457a9 | |||
| e4abf6e723 | |||
| 1339ebaa84 | |||
| c9b90884da | |||
| 9b2b2c88df | |||
| e5bdab0355 | |||
| 4d46958c82 | |||
| 9dd8e4df7f | |||
| d98e07c3d3 | |||
| 78bc11465b | |||
| 8e8e4bbabc | |||
| 90671233c6 | |||
| 12bae51384 | |||
| 7b848e215f | |||
| 21872e2fb0 | |||
| 2a218b96c4 | |||
| e76cda6923 | |||
| 9d16612a9b | |||
| 63c865ace6 | |||
| 0a62de0d4f | |||
| 593996216f | |||
| 4eae23a2cc | |||
| f3699b5ac8 | |||
| 9ce0e51305 | |||
| 4c79318694 | |||
| f7ac724c5d | |||
| ee9fe1239a | |||
| b6b5c27cec | |||
| 632e07b749 | |||
| 48cd2d190f | |||
| 685797f403 | |||
| ef6f421f89 | |||
| e0ffd3e8a5 | |||
| 0d16b5fc38 | |||
| ac8a27cba9 | |||
| e5f2a8ebf2 | |||
| 54733eba6f | |||
| 93353aea70 | |||
| e16cb8b4a2 | |||
| 5bf3c1df24 | |||
| 419918076e | |||
| fb768c420d | |||
| eb067fee55 | |||
| 6390b50d6e | |||
| 5d8134ed32 | |||
| 852904e1a4 | |||
| a120adde63 | |||
| a80af177b6 | |||
| 8db7d435b9 | |||
| 901e0ddfe4 | |||
| ecb30409f6 | |||
| 44c2c77548 | |||
| 5be5efdacf | |||
| 057c3da82a | |||
| 8fa429caef | |||
| 87f526d82f | |||
| 1ae2320e09 | |||
| 54693cf7b1 | |||
| a082375d57 | |||
| 9c7adb7248 | |||
| ccebbbc0ac | |||
| ebb6915e58 | |||
| 5cc27fd3b5 | |||
| a332509e02 | |||
| 375fe81311 | |||
| d354ad1c34 | |||
| 119d8b3aca | |||
| cd9edba26f | |||
| 8f1c502d2b | |||
| 92312fbc0c | |||
| 2efcaa9e8e | |||
| aa53541235 | |||
| b863c25d21 | |||
| f77c3574af | |||
| f5105bac65 | |||
| 5a86592e93 | |||
| 2c83cfc14c | |||
| 863546e125 | |||
| 9198e30688 | |||
| 1890157faa | |||
| 0898f372b1 | |||
| b9e5256cf9 | |||
| 6b6d89b911 | |||
| d3e0193c8a | |||
| 31881209d6 | |||
| 5c7e893393 | |||
| 3c814ebf87 | |||
| 5cf1dca36e | |||
| 12338c1dc4 | |||
| 5b23752205 | |||
| 4e53f301d8 | |||
| 2b7803dbac | |||
| 446a278f3d | |||
| 0047d3f81a | |||
| 4e1f17d65b | |||
| f9b1dbe2ac | |||
| a251474144 | |||
| 8d88bb06b2 | |||
| 9f2ff3ed22 | |||
| 45cbf70265 | |||
| 59e16b88ae | |||
| 33f219dfe6 | |||
| 44db2eea70 | |||
| 12ab54648c | |||
| 19926e2979 | |||
| 1620a1e014 | |||
| 888546b6f5 | |||
| 3215db26aa | |||
| 76aff84788 | |||
| fc28ba3156 | |||
| effce0573b | |||
| e8db363431 | |||
| 9603b6877d | |||
| d5ecb5ff5a | |||
| dae73938e8 | |||
| 619b6dfae3 | |||
| 8f9c36b730 | |||
| 3eeec4faae | |||
| 972a4b95b6 | |||
| ffee1a4126 | |||
| 96e23c2ff6 | |||
| 08356007c9 | |||
| 5064b6f747 | |||
| 57d3002ee1 | |||
| a00a0dbfcd | |||
| b41d2c5c14 | |||
| 1da48beeec | |||
| b57ff73086 | |||
| 67978b5746 | |||
| 062f305d1a | |||
| 1f70d4e2a5 | |||
| aa5bc20c83 | |||
| 09af10f635 | |||
| 4d7953aa56 | |||
| 46e1560678 | |||
| 4d0148b417 | |||
| 1605d1d24d | |||
| 5190043e56 | |||
| f66a2ffa1e | |||
| d1e76a34a0 | |||
| 5b3d5f9f3c | |||
| 415a42f327 | |||
| 09f6e55338 | |||
| a351e05a17 | |||
| d37bcbdc92 | |||
| 437af37b13 | |||
| c62367612d | |||
| a92cba8484 | |||
| 5f7d922b10 | |||
| dc29632d4e | |||
| f4a7754cc0 | |||
| 6811d3d80b | |||
| 245f6273bd | |||
| 870c8d3c4e | |||
| d573472a86 | |||
| 441b6dbda0 | |||
| a7e6a1059c | |||
| 85719a0a5d | |||
| b5b52afd35 | |||
| dc35633aa4 | |||
| 9e3ba487fa | |||
| aee8425b68 | |||
| 94229bb262 | |||
| 1f6444fbea | |||
| 439ef6447d | |||
| 9cab808c5d | |||
| d41fcf7345 | |||
| ac51ba38f9 | |||
| ef85b24a78 | |||
| d88730685e | |||
| 16661847a7 | |||
| 7f782a1a24 | |||
| 9188ce68aa | |||
| 2b79a6ff8f | |||
| 70b0274c8e | |||
| 83ce1de8e7 | |||
| b1d484f827 | |||
| 123519165d | |||
| 30ff9c6775 | |||
| 906f5f7e96 | |||
| 9238316cf1 | |||
| 5e89b9a455 | |||
| e3a4ff33d2 | |||
| 5d9ea394ba | |||
| abb5c9fd92 | |||
| 266835cd2e | |||
| 92af03579c | |||
| 2e20f2b89f | |||
| e67593673f | |||
| d1b533d399 | |||
| 2647902fee | |||
| 574320ec3f | |||
| 3f2377017c | |||
| 2b5bb02817 | |||
| 302d14adef | |||
| b796ededae | |||
| f811ba8777 | |||
| eb7b45d26b | |||
| 17b2d92a3d | |||
| 22f0bcaf8f | |||
| e61277002c | |||
| ca5258f140 | |||
| 8f4473b3e3 | |||
| 51e8af9e5f | |||
| 82818e7324 | |||
| 6ae8103022 | |||
| eca2d92791 | |||
| 6778e19710 | |||
| 25f25275cd | |||
| 7e746ad2a6 | |||
| 6ffa2b01e1 | |||
| ed6ca0d7fa | |||
| 8e2a3c1d2f | |||
| 7f6dcc2745 | |||
| 76e34d6f2c | |||
| e613b17c05 | |||
| 5ba9a089e1 | |||
| f2d5d6d24e | |||
| a1ec4ea3a9 | |||
| 0fe7420638 | |||
| b304730225 | |||
| 4801526f35 | |||
| f1857030b5 | |||
| b5b3f4e1c6 | |||
| 172bb7887c | |||
| 60228d30d1 | |||
| 9592537840 | |||
| 8768a80242 | |||
| d5f73f89d8 | |||
| 19bbe6c67d | |||
| aebb65e983 | |||
| 5e327af327 | |||
| bc1f8813c2 | |||
| 80d9f624d0 | |||
| e9c46f38fc | |||
| ecfbaa267d | |||
| c25fd3349b | |||
| c3e27bcf87 | |||
| a5894f3e6b | |||
| 4db3a388dd | |||
| 6fd1a2ef52 | |||
| fe2a259eb1 | |||
| 1ba7c2f276 | |||
| 649f747f8a | |||
| 05dbaf7672 | |||
| 742a08229e | |||
| 5602d2c7bb | |||
| f3e0479a8f | |||
| a1143c4ea0 | |||
| 0314d1dd01 | |||
| 751b3f502d | |||
| bf5e09d5ab | |||
| 14e4a10312 | |||
| 53b89e1ee4 | |||
| 370f878a36 | |||
| 6e4d61c1fd | |||
| f6fe5c07f6 | |||
| c685293297 | |||
| 0e6a2c0491 | |||
| c2209ad5e4 | |||
| 5f249a3e67 | |||
| 76fb3652fc | |||
| 92925e846d | |||
| 43c04c29ce | |||
| 06b74c87da | |||
| 7f075b0b15 | |||
| c5a86c22a4 | |||
| 3621c6234c | |||
| 80c2fefc43 | |||
| a47952146a | |||
| a55950865e | |||
| ab181ac329 | |||
| db172d1053 | |||
| dad26339a9 | |||
| 3b0ed61826 | |||
| 9699e2b483 | |||
| 3048188b5b | |||
| 547bb3b053 | |||
| 7c2087cf05 | |||
| 217fea9667 | |||
| 523c3cd50b | |||
| 631126c77a | |||
| 655d381ef3 | |||
| c68fec7e97 | |||
| cdfa8a668b | |||
| 92651d228d | |||
| 90e3692603 | |||
| 3a8316ab93 | |||
| 8d3f0d0eab | |||
| ded0efb955 | |||
| cdd4354256 | |||
| bde955fc56 | |||
| abc9e98625 | |||
| d086ee14dd | |||
| f43fec7ee6 | |||
| 6385511e88 | |||
| ed4becf007 | |||
| f11ab4c569 | |||
| b12c2c76d1 | |||
| f5589445b9 | |||
| 032a61b197 | |||
| 011ed380aa | |||
| 88a18c8b6a | |||
| 51e65db715 | |||
| cc02fcd889 | |||
| 9f17c62533 | |||
| 36bd2a65e3 | |||
| 85d4e56bb1 | |||
| 381d9bafdf | |||
| ada16fd188 | |||
| c408157a4d | |||
| 6e299b582a | |||
| 9777fbacf6 | |||
| 643b4dd126 | |||
| 19ac54277b | |||
| c78a8dfd2d | |||
| b1a57c4cb2 | |||
| 54c180092d | |||
| be110d0464 | |||
| 6e733b65ae | |||
| f948a2d0c0 | |||
| 2aa47554fc | |||
| c80b270678 | |||
| dcc32e84b9 | |||
| 947d610309 | |||
| 3e01a387ba | |||
| 4dbba5ac98 | |||
| 374cc4183e | |||
| b9d9730b62 | |||
| 0a178a687a | |||
| c4c43c3d26 | |||
| 8fa86d4d34 | |||
| a22dd28e02 | |||
| 0e274fc4be | |||
| bc3da25a4a | |||
| 80492d663e | |||
| 172c539a5a | |||
| a079acc0d9 | |||
| 30df77fa4c | |||
| 71a22e45b0 | |||
| defd8a527b | |||
| 3ce29236f3 | |||
| 04ee99f1a3 | |||
| 91817bffe1 | |||
| c39b83667b | |||
| 1bd382c1d0 | |||
| 49bef1cdbf | |||
| 249c508126 | |||
| 04b27525fa | |||
| 175bcb1734 | |||
| fec2c7e715 | |||
| 07dca8cc03 | |||
| 60c093f086 | |||
| db4ab1c936 | |||
| f071207463 | |||
| 622b9d9276 | |||
| 05bfdeab7a | |||
| b4bb98ea60 | |||
| 792b7e0629 | |||
| a079c2eb7c | |||
| f7aa91e660 | |||
| 6d677bbd63 | |||
| cee3ec6dc4 | |||
| 3da17c42a4 | |||
| 2329cbc1a2 | |||
| b39ee54103 | |||
| 299f9837b7 | |||
| 6a889ed3e5 | |||
| f3ba88c87c | |||
| 498f1525b2 | |||
| e7c5120682 | |||
| 19cfaa2be7 | |||
| e97c7e042b | |||
| d8b1fc45aa | |||
| 35f27d0d3e | |||
| 330a11861e | |||
| 4827fe86bb | |||
| 72c55b56f2 | |||
| 295da7e5f3 | |||
| 4eab85d364 | |||
| 3cc83ce024 | |||
| 52c423a423 | |||
| 952f8e38cf | |||
| 542b3e8a64 | |||
| 4f79eb256d | |||
| 7620456486 | |||
| 052d209901 | |||
| e9c45ff406 | |||
| f1053d48a2 | |||
| ba12f52f6c | |||
| 456137fa24 | |||
| 692059e899 | |||
| 252ce0b581 | |||
| d24befa0bc | |||
| 5462710103 | |||
| d1b923bee9 | |||
| 81a6d1b0d4 | |||
| 04020f391a | |||
| c4ab0c09ea | |||
| 6e50e4b9ee | |||
| 1599f9f0c0 | |||
| 0c5b6e5556 | |||
| e3e04f5dae | |||
| 17bc8565f6 | |||
| c08954c18b | |||
| 7ba56a4b88 | |||
| 9b7f40ce4d | |||
| b70370f3fd | |||
| 4d3cf77ad5 | |||
| b2005ccaef | |||
| 659cf7249e | |||
| 62a010a25d | |||
| 6b4ea68bc7 | |||
| d6891c705e | |||
| 9bcb006ec7 | |||
| 02ac6ec81c | |||
| 5c91f5b71d | |||
| 16b674b984 | |||
| 65392d5e6b | |||
| 41d108ead6 | |||
| 0c9dbc61a1 | |||
| 6788fdb0d6 | |||
| 3a4b61579d | |||
| 51d7ba7446 | |||
| e608adea60 | |||
| 8dd6882222 | |||
| 5aef565fb6 | |||
| a4d6bcba09 | |||
| f09a577ab5 | |||
| 973e1acb67 | |||
| 676a724491 | |||
| 73318fd514 | |||
| cb08c15616 | |||
| a3287b85c5 | |||
| 0c0b1ec9ae | |||
| d2f87ca76c | |||
| 4935b14539 | |||
| 0835611d3a | |||
| 8b4fa2605e | |||
| c3910807c5 | |||
| c5b8b5687f | |||
| f61883b227 | |||
| 35ff9af6ce | |||
| dad2b9aac8 | |||
| 1613d30544 | |||
| b6df9debaf | |||
| b9d0dc60b0 | |||
| 37b1876807 | |||
| d206350738 | |||
| 2da1f9181a | |||
| bd396e1fd5 | |||
| f55c9ed1ba | |||
| 5da69c0b9a | |||
| a806e8cc58 | |||
| 369b260e12 | |||
| d9e7c1626a | |||
| 1a1a7bbbfd | |||
| 33e97e994d | |||
| 11e6848bb9 | |||
| 829410729c | |||
| 4995aecd62 | |||
| 0e2a3686c0 | |||
| 66b2140892 | |||
| 0d2857a242 | |||
| 17d99e6266 | |||
| ea7d4be3f8 | |||
| 05db8784ae | |||
| 68667d6057 | |||
| d58b5ef74b | |||
| f044037ec5 | |||
| a97f21ba4e | |||
| b594ed99b8 | |||
| 58b06222ff | |||
| 58dc397930 | |||
| 15073d63d9 | |||
| a6277370ca | |||
| 31b2d6be75 | |||
| 57ee14d62d | |||
| d470cfe86e | |||
| b55d8f46f4 | |||
| c15218e37a | |||
| 985aa0423d | |||
| c14a8dce93 | |||
| f5d45221ca | |||
| d668aa7c24 | |||
| e20fe421e7 | |||
| 2deb38d615 | |||
| b95d71af2b | |||
| ebe4ca6b60 | |||
| f159ed20c2 | |||
| cdbb042ce4 | |||
| 23bbe511fe | |||
| 444218e755 | |||
| 9cc60c9dd3 | |||
| cc1fbe0956 | |||
| 2c226d597d | |||
| c6ab32ffb9 | |||
| 97c6ec6d49 | |||
| 1fcf7ba5bc | |||
| 12c1e1d149 | |||
| fa222b0ea2 | |||
| 101be77d9d | |||
| a6dbef89c2 | |||
| 02f08879a4 | |||
| 61f1ee2d2d | |||
| ac4b592b4e | |||
| 93b6e80cd7 | |||
| f5de714451 | |||
| d4741eece1 | |||
| 585484cb06 | |||
| b696928a5b | |||
| 79d4e865fe | |||
| 8380879804 | |||
| 091461cece | |||
| d228c5459d | |||
| 3d5d3ea20c | |||
| de7f8eec04 | |||
| 4b6047e746 | |||
| c47673bf10 | |||
| 49432009fe | |||
| 2f6d2b08aa | |||
| 473f10877c | |||
| c7df82460c | |||
| b19697e3ac | |||
| 3e51448ef0 | |||
| 2b2e515a30 | |||
| 394e640909 | |||
| b48eb4e88b | |||
| b525480b25 | |||
| 45f18eaa52 | |||
| 4c92a2869b | |||
| 8041ab8a61 | |||
| 8251fc0811 | |||
| 827ff80c06 | |||
| 18ca998f67 | |||
| cb286a66be | |||
| 8444470e3a | |||
| f33828a1ca | |||
| 68e425f869 | |||
| da6344297a | |||
| 3cfca01372 | |||
| d934bb15b0 | |||
| 0c0a8392e5 | |||
| 98b6ce353c | |||
| 58043dac0f | |||
| d2c1f1131b | |||
| fa5c7a9e75 | |||
| ceb94d52a1 | |||
| a2716712ab | |||
| 1ac7baceff | |||
| 968d94d417 | |||
| 7842181b47 | |||
| 2ce47fda88 | |||
| ffd010767f | |||
| 635990a5b0 | |||
| 562f2375c5 | |||
| edf533c83e | |||
| c1d61c88e9 | |||
| 6360b846c6 | |||
| 57900d07f0 | |||
| 8e72e1ed88 | |||
| 10c547396d | |||
| 66dd871288 | |||
| d484939c02 | |||
| 85fd8729ce | |||
| b3e16c6423 | |||
| 30d6766db4 | |||
| 17234f82d0 | |||
| 7b57df02a7 | |||
| b65ae3b036 | |||
| bce76a7977 | |||
| 66f3e97457 | |||
| 0ee61d178f | |||
| 1ceba29f4b | |||
| 40c748a2ae | |||
| 0e9453a395 | |||
| 69d0bc8fd5 | |||
| 6a73e5a720 | |||
| e70ba29d95 | |||
| e5647cf70d | |||
| 9637cf0574 | |||
| 74cc63ba2f | |||
| 0b6e360602 | |||
| a49cda6523 | |||
| d612c72405 | |||
| eb152d7431 | |||
| 6bd143dd25 | |||
| 770d3eabc0 | |||
| 75e2ba5af3 | |||
| 1726bb6c0d | |||
| 5dfe65d53a | |||
| 83afd09f13 | |||
| d059cc7170 | |||
| 96488c1c74 | |||
| 84a81579ba | |||
| 244ba1a61a | |||
| 9dadc06e64 | |||
| 60f949e36f | |||
| af154e3053 | |||
| 9e6c290696 | |||
| 0a71063530 | |||
| 0b1ae11498 | |||
| 017a4e7c30 | |||
| 3891f18e71 | |||
| 6a2077cbd8 | |||
| aa11cc19e8 | |||
| 9267536fee | |||
| a6f5717567 | |||
| 0a58d6812a | |||
| 12507aab8a | |||
| d376fe9e17 | |||
| d21622bef4 | |||
| 7febec49b2 | |||
| 14d5098ca2 | |||
| bc8eac2439 | |||
| 4e65db80e8 | |||
| c0c71d6b3a | |||
| bac1c6d12f | |||
| ce68291d83 | |||
| 4176a0ade3 | |||
| ec10f2e72b | |||
| f36c268b9e | |||
| 824392a1c2 | |||
| 1f9a7b8fd3 | |||
| 9379e85e23 | |||
| 805c2832c1 | |||
| d33a048d89 | |||
| f77fdc0ce8 | |||
| 7da51787b9 | |||
| b1f422c1c5 | |||
| b3f966e2ca | |||
| 3f191e1b75 | |||
| 6d5fdfbf73 | |||
| 9a9e457dd6 | |||
| c316dbe2aa | |||
| b5fcb06a76 | |||
| b5a9a6793b | |||
| 0cf79155d4 | |||
| f8f9f3c438 | |||
| 1926e919be | |||
| e6c68eed51 | |||
| f9e747dbc6 | |||
| 0e86e292e4 | |||
| a590682764 | |||
| 31c40fa4cc | |||
| 1feb3838b5 | |||
| bd0732b1d0 | |||
| 0b5cbcefdd | |||
| e4a87f2f4f | |||
| 3c8cadf7ca | |||
| 7c0b26e8a0 | |||
| 982503e9a8 | |||
| 3d93675ff9 | |||
| 53d6c9b9c0 | |||
| a02e90d502 | |||
| 238dbffb48 | |||
| a9d7b6eab7 | |||
| 39c3334147 | |||
| 4223495e6c | |||
| 023e86d68f | |||
| ac57be91e1 | |||
| c2e65bafb5 | |||
| 74161b2122 | |||
| 39ee5c5a46 | |||
| 788f330d07 | |||
| af56151231 | |||
| 34d359fe03 | |||
| 4672dbda2a | |||
| 62252d157e | |||
| b1cf550123 | |||
| 9c84749e2c | |||
| cca4c47781 | |||
| 17bd9a1fa1 | |||
| 0321644bbd | |||
| 81e7988eb9 | |||
| 4985311d46 | |||
| 05348f3250 | |||
| 003609e565 | |||
| e0cfaee7aa | |||
| 9537a909f7 | |||
| e75387f029 | |||
| 8c2dd5fb9a | |||
| 27545dcc86 | |||
| 724e04e979 | |||
| dfc94c58f0 | |||
| 4b0f8d76f4 | |||
| fac895d7ba | |||
| d023f316ac | |||
| 04b40ff221 | |||
| 03a08435e2 | |||
| 4dd3ab8f32 | |||
| 8e0660ad54 | |||
| 1f42512199 | |||
| 1a29ea1038 | |||
| eab2b9dc09 | |||
| 94e92cd6c0 | |||
| 57cd6d2de1 | |||
| 822d468232 | |||
| bdaa6a1910 | |||
| 2221dcc9f2 | |||
| 2eb1ee967c | |||
| c49cfefe88 | |||
| c6a6f39d29 | |||
| a3d7811f24 | |||
| eb56ca3b0d | |||
| 755e0143fb | |||
| dfa48094dc | |||
| e585192eeb | |||
| 646924fce8 | |||
| 13c6eb42e9 | |||
| e5fb50476c | |||
| 073c590d0b | |||
| c63aa7f085 | |||
| c832e62db0 | |||
| b7a7119b1f | |||
| 19a880bb91 | |||
| 672399c751 | |||
| c54abde1bd | |||
| 95c1d2a887 | |||
| 3e6f27522b | |||
| 1b70f94282 | |||
| ebef84e9ea | |||
| 87d4970e8b | |||
| b1a772d194 | |||
| 4938765eb3 | |||
| cce78cc5e2 | |||
| f11f2bfb56 | |||
| 24f43e7ae9 | |||
| 9085b933d8 | |||
| d94d469c86 | |||
| 59502594f8 | |||
| d20c9bde7e | |||
| 62414e3073 | |||
| 505dde09de | |||
| 603d623eda | |||
| 87ebf2e50b | |||
| 37c3f0d8a0 | |||
| 48c985e775 | |||
| 7358fffb0f | |||
| de5b6386e0 | |||
| 1de2d5c2b6 | |||
| ef53a9229f | |||
| 259c39a63a | |||
| 4d87f6025e | |||
| 327b98eb13 | |||
| f977d10a19 | |||
| a0cf8c322d | |||
| 627be179c1 | |||
| 1e74f5850b | |||
| 6d83a73858 | |||
| 9b76872708 | |||
| 9b093c9a12 | |||
| 4d587c341b | |||
| f8f6cd6ef5 | |||
| cf08eac15e | |||
| 9a8552e8ae | |||
| 846317ef37 | |||
| 7e62789edf | |||
| 5865af7f6e | |||
| 852663f6d2 | |||
| c1148c4ea6 | |||
| 280dc77f8b | |||
| a9b30984a3 | |||
| 2f83c3b689 | |||
| b25ad12f1a | |||
| d95e43a6a1 | |||
| 27df987211 | |||
| 982745fb83 | |||
| 8fa8d471af | |||
| 2cc14bd0fb | |||
| 98ad72b096 | |||
| fdc8ed8d05 | |||
| 24fcb7f813 | |||
| 236c64a17d | |||
| 9e835e8edb | |||
| f96569da1e | |||
| 91ff45fbde | |||
| 1261f250c6 | |||
| 3673b45437 | |||
| 45aabc5d0d | |||
| f9bd83c854 | |||
| 499d8adb75 | |||
| 54386c82fd | |||
| 86a51015b1 | |||
| 38b9ec7a18 | |||
| 998406d20e | |||
| f7b4b750d8 | |||
| 2558ab3de7 | |||
| a4e2c56317 | |||
| 0c10ae1861 | |||
| b3cc828995 | |||
| ba8f9d8620 | |||
| 3c89a28a06 | |||
| 9c5d7716e2 | |||
| 46fd26e366 | |||
| 41a2eb5245 | |||
| c410d7a97d | |||
| 6fa63dcc0c | |||
| 3d7670a6ba | |||
| 96f25332ea | |||
| 3385d38648 | |||
| 1618c963e4 | |||
| 50462dcdc6 | |||
| 1e3be09b3b | |||
| 6e66a9222a | |||
| c3ac834526 | |||
| 9d1e8b1e1d | |||
| f605373a2b | |||
| 56b7622612 | |||
| 696a6ccd57 | |||
| 51b03b87e6 | |||
| aa7ba0bc1a | |||
| 07e4076585 | |||
| de1a459879 | |||
| 1aacb9bb15 | |||
| 9b4ecc96f6 | |||
| e3f4f874c5 | |||
| 6ace801418 | |||
| d31b93b513 | |||
| ac0fd6aa9a | |||
| c7e0888982 | |||
| 068f33cfdf | |||
| 4807cd8a6e | |||
| c703f1eed6 | |||
| 5ac5da3524 | |||
| 0c13d34ade | |||
| 35e824c287 | |||
| 1e0d290f2e | |||
| 0097a8d097 | |||
| 36cc43170d | |||
| 5578ad5e14 | |||
| d11f0a709d | |||
| 0a43b23275 | |||
| 7967683296 | |||
| 5b2c016834 | |||
| aaff125608 | |||
| 407adc7061 | |||
| d0e612dc36 | |||
| 5aa7435d25 | |||
| 7c23ec90a9 | |||
| 390957fec4 | |||
| 060a76dc3e | |||
| 6625810d2a | |||
| edc442afdb | |||
| 16b9514543 | |||
| 95c7f4a7f0 | |||
| ae6fabc6fe | |||
| 7eaadf616c | |||
| 8fed5fc5ae | |||
| f25951c412 | |||
| c11195d5e3 | |||
| 2ed5cba110 | |||
| 4c05a697fa | |||
| 1259a474ba | |||
| 3995deaf76 | |||
| 076587425e | |||
| da6aeaca46 | |||
| 8ee33ca551 | |||
| ea7f13922b | |||
| 38d0063c36 | |||
| 56d0d5986f | |||
| df83459721 | |||
| 54a9e00970 | |||
| 9bda96d39e | |||
| 053470d5a8 | |||
| 6f4160c014 | |||
| 65ef82a946 | |||
| b509a7060a | |||
| 5ad6ff239b | |||
| fdaa6ff9e3 | |||
| 2f31763335 | |||
| 350562919c | |||
| aa5c4945d6 | |||
| 6fbfc58602 | |||
| 77a5c43d50 | |||
| f28e4b86fb | |||
| 6801dd043d | |||
| b675e6ab77 | |||
| d6306f8ccb | |||
| a9817e9127 | |||
| bb5f33d13c | |||
| c08897cd10 | |||
| 384875f4fc | |||
| 9cfa84313c | |||
| f787c49b53 | |||
| fa90e14b06 | |||
| fe625a558e | |||
| 03b989251d | |||
| 95919051e0 | |||
| 46fb88c76f | |||
| 210bfaf8d6 | |||
| a50dec88d5 | |||
| 8dcec034ed | |||
| 9ef41f68fb | |||
| 05d733e707 | |||
| 4bbe28bdf0 | |||
| 0c01cf7c85 | |||
| 917cd13ce2 | |||
| cfb36443fb | |||
| 9d3826c676 | |||
| 4300bb2e1f | |||
| 6edc438789 | |||
| 955cf35d5f | |||
| 25cd7c7c50 | |||
| 0f8efb07c7 | |||
| 732cb6c45c | |||
| 4d63a89fa6 | |||
| 266a868ba9 | |||
| 8199967b31 | |||
| 9d61c18143 | |||
| 7c73e28a6d | |||
| 221bfa4c67 | |||
| aaca4987c9 | |||
| 1a8b7f7513 | |||
| 992b47b991 | |||
| 21d0f40751 | |||
| 5e7f06397f | |||
| adaace4ab8 | |||
| 739ff84732 | |||
| 2a177052de | |||
| 424eaba4c5 | |||
| e1cafa3834 | |||
| ba539eb9aa | |||
| 24de676a64 | |||
| 0c2741f7ad | |||
| f7c82baee9 | |||
| 2b34e0abdc | |||
| 6306bc3ddc | |||
| ea068dcc2c | |||
| 633fedaa96 | |||
| 4ff76cad2a | |||
| 65134c793b | |||
| 5af09e73f2 | |||
| d5f34cf34c | |||
| 6a2e559222 | |||
| cefa602601 | |||
| d773691848 | |||
| da07ad16c1 | |||
| f40707dc68 | |||
| 2d8ce500fa | |||
| ba0cea6826 | |||
| ddf1b04cce | |||
| ad5b3a4753 | |||
| 531ea5b3a2 | |||
| b468468e7e | |||
| d52e4e5df3 | |||
| 907743eee7 | |||
| 610e3dccb7 | |||
| 27392f832d | |||
| e9db7fea5b | |||
| bdd3930855 | |||
| cff0168f3a | |||
| 70d5c88026 | |||
| d83901e665 | |||
| 1e1984a586 | |||
| 2f180cea7f | |||
| f4d6a3ec4e | |||
| 7aa922ceac | |||
| 06dcc5a2c6 | |||
| 000f762fb9 | |||
| 3bc3eeb5da | |||
| 4e5699fa71 | |||
| acc576658a | |||
| a76274b549 | |||
| 803ff8ebb9 | |||
| b42152ffeb | |||
| 4015a5486c | |||
| 024b43ca06 | |||
| aae48e6fd7 | |||
| d29c7e7871 | |||
| 9448fe3db4 | |||
| 3817f3a89b | |||
| 755f4f324b | |||
| 863ab0e72e | |||
| 4ab0377c6e | |||
| 2062a7ca8f | |||
| b61a55eebf | |||
| c30078c5a3 | |||
| 39b91c97f0 | |||
| 8334ee18e6 | |||
| cc2592f582 | |||
| 96d35f7c54 | |||
| 98c5fc6ae2 | |||
| fbde0c6c96 | |||
| 602e7c83e2 | |||
| eb9218a86b | |||
| 9f2dcc3f13 | |||
| bc210b292b | |||
| 2113af9c52 | |||
| 6f417b57c1 | |||
| a7742d7d63 | |||
| 5179e37bd1 | |||
| a7b17bfaf0 | |||
| 4af1f31a3f | |||
| 0acd06d13c | |||
| fd22e98298 | |||
| 9e42e04b4a | |||
| 9103837228 | |||
| 3f3c5de851 | |||
| 167a12028d | |||
| 6af2faebd2 | |||
| 34b65be44a | |||
| fd16222613 | |||
| 1ba6cd8423 | |||
| b928ebdd53 | |||
| b42623ff9d | |||
| 59ae0e0013 | |||
| 4788de784b | |||
| 926535469d | |||
| c0f63eb21f | |||
| 5627a0cbdf | |||
| ed2a698392 | |||
| aaad1791d9 | |||
| ad6e82942b | |||
| 9a9954a036 | |||
| d60bb57d4b | |||
| 591708903b | |||
| f9d62fba7a | |||
| 85dde8a800 | |||
| 9d039c206b | |||
| cbff19ff1a | |||
| 4c3f9b2ef4 | |||
| 167bac23aa | |||
| 5d0cfa2527 | |||
| 0e523618a1 | |||
| 821fae0d94 | |||
| 3b26105f68 | |||
| 0f2f966a91 | |||
| d7d491d445 | |||
| 41effbe2da | |||
| 9b0d6862c4 | |||
| 890fcdf842 | |||
| 18dbac203f | |||
| 8d1f254dcc | |||
| e5841d3126 | |||
| 90df3af6cf | |||
| 11cc36d770 | |||
| 05f1939b02 | |||
| 050ea9762f | |||
| 0f24d4d2a1 | |||
| fc799191f4 | |||
| 8fad85edda | |||
| d70053aba5 | |||
| b699fe7a9d | |||
| 94c67faaea | |||
| b2ed5c3070 | |||
| 9fe49497bb | |||
| 5b8c10f2f8 | |||
| 24983f62e2 | |||
| f2057ce1ab | |||
| 6797fd65a5 | |||
| bf489feef1 | |||
| 947e06a860 | |||
| 6a3d925a47 | |||
| 04d5ba266f | |||
| 90be83ae99 | |||
| 5e80bd3cc9 | |||
| fb7ef76e74 | |||
| db4b1e613c | |||
| ee39081b11 | |||
| 7d842f5bcf | |||
| 4eac198270 | |||
| faac32418c | |||
| 42810621df | |||
| 61a5378aeb | |||
| 42d644ef91 | |||
| c95a56450d | |||
| dc5199feea | |||
| f88fdf6a1b | |||
| b68057d927 | |||
| e9a860d9cb | |||
| 8be86cbdfd | |||
| 5091e64a42 | |||
| 828304d587 | |||
| 9d584475f6 | |||
| bb60cb0bf9 | |||
| 25f908b320 | |||
| 9b7dca2fa1 | |||
| 55e1dfb778 | |||
| 735a79ae83 | |||
| ef2b400c61 | |||
| c2263db7bc | |||
| 53eca2ff5b | |||
| 7bbbda71df | |||
| 3a15a3821a | |||
| 9557b9f70f | |||
| 464441d8c3 | |||
| f30f1afd47 | |||
| b3db37b99d | |||
| 7a276f39fb | |||
| 415668ecf0 | |||
| 651967b95c | |||
| 8e0baf257c | |||
| c8268e65fd | |||
| 3cf4375387 | |||
| 438e2dc228 | |||
| c1adbe3189 | |||
| 7ee1816612 | |||
| b4084491e5 | |||
| 8f4f834ce6 | |||
| 411fd2b761 | |||
| 61d7d67c39 |
@@ -34,11 +34,11 @@ This is a template helping you to create an issue which can be processed as quic
|
||||
- [ ] I report the issue, it's not a question
|
||||
<!--
|
||||
OpenCV team works with forum.opencv.org, Stack Overflow and other communities
|
||||
to discuss problems. Tickets with question without real issue statement will be
|
||||
to discuss problems. Tickets with questions without a real issue statement will be
|
||||
closed.
|
||||
-->
|
||||
- [ ] I checked the problem with documentation, FAQ, open issues,
|
||||
forum.opencv.org, Stack Overflow, etc and have not found solution
|
||||
forum.opencv.org, Stack Overflow, etc and have not found any solution
|
||||
<!--
|
||||
Places to check:
|
||||
* OpenCV documentation: https://docs.opencv.org
|
||||
@@ -47,11 +47,11 @@ This is a template helping you to create an issue which can be processed as quic
|
||||
* OpenCV issue tracker: https://github.com/opencv/opencv/issues?q=is%3Aissue
|
||||
* Stack Overflow branch: https://stackoverflow.com/questions/tagged/opencv
|
||||
-->
|
||||
- [ ] I updated to latest OpenCV version and the issue is still there
|
||||
- [ ] I updated to the latest OpenCV version and the issue is still there
|
||||
<!--
|
||||
master branch for OpenCV 4.x and 3.4 branch for OpenCV 3.x releases.
|
||||
OpenCV team supports only latest release for each branch.
|
||||
The ticket is closed, if the problem is not reproduced with modern version.
|
||||
OpenCV team supports only the latest release for each branch.
|
||||
The ticket is closed if the problem is not reproduced with the modern version.
|
||||
-->
|
||||
- [ ] There is reproducer code and related data files: videos, images, onnx, etc
|
||||
<!--
|
||||
@@ -61,9 +61,9 @@ This is a template helping you to create an issue which can be processed as quic
|
||||
to reduce attachment size
|
||||
* Use PNG for images, if you report some CV related bug, but not image reader
|
||||
issue
|
||||
* Attach the image as archive to the ticket, if you report some reader issue.
|
||||
* Attach the image as an archive to the ticket, if you report some reader issue.
|
||||
Image hosting services compress images and it breaks the repro code.
|
||||
* Provide ONNX file for some public model or ONNX file with with random weights,
|
||||
* Provide ONNX file for some public model or ONNX file with random weights,
|
||||
if you report ONNX parsing or handling issue. Architecture details diagram
|
||||
from netron tool can be very useful too. See https://lutzroeder.github.io/netron/
|
||||
-->
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request
|
||||
|
||||
- [ ] I agree to contribute to the project under Apache 2 License.
|
||||
- [ ] To the best of my knowledge, the proposed patch is not based on a code under GPL or other license that is incompatible with OpenCV
|
||||
- [ ] The PR is proposed to proper branch
|
||||
- [ ] There is reference to original bug report and related work
|
||||
- [ ] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
|
||||
- [ ] The PR is proposed to the proper branch
|
||||
- [ ] There is a reference to the original bug report and related work
|
||||
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
|
||||
Patch to opencv_extra has the same branch name.
|
||||
- [ ] The feature is well documented and sample code can be built with the project CMake
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
name: PR:4.x
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- 4.x
|
||||
|
||||
jobs:
|
||||
ARM64:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-ARM64.yaml@main
|
||||
|
||||
U20:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-U20.yaml@main
|
||||
|
||||
W10:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-W10.yaml@main
|
||||
|
||||
TIM-VX:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-timvx-backend-tests-4.x.yml@main
|
||||
@@ -0,0 +1,25 @@
|
||||
name: lint_python
|
||||
on: workflow_dispatch
|
||||
jobs:
|
||||
lint_python:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
- run: pip install --upgrade pip wheel
|
||||
- run: pip install bandit black codespell flake8 flake8-2020 flake8-bugbear
|
||||
flake8-comprehensions isort mypy pytest pyupgrade safety
|
||||
- run: bandit --recursive --skip B101 . || true # B101 is assert statements
|
||||
- run: black --check . || true
|
||||
- run: codespell || true # --ignore-words-list="" --skip="*.css,*.js,*.lock"
|
||||
- run: flake8 . --count --select=E9,F63,F7 --show-source --statistics
|
||||
- run: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=88
|
||||
--show-source --statistics
|
||||
- run: isort --check-only --profile black . || true
|
||||
- run: pip install -r requirements.txt || pip install --editable . || true
|
||||
- run: mkdir --parents --verbose .mypy_cache
|
||||
- run: mypy --ignore-missing-imports --install-types --non-interactive . || true
|
||||
- run: pytest . || true
|
||||
- run: pytest --doctest-modules . || true
|
||||
- run: shopt -s globstar && pyupgrade --py36-plus **/*.py || true
|
||||
- run: safety check
|
||||
Vendored
+26
-17
@@ -1778,30 +1778,30 @@ TegraCvtColor_Invoker(bgrx2hsvf, bgrx2hsv, src_data + static_cast<size_t>(range.
|
||||
: CV_HAL_ERROR_NOT_IMPLEMENTED \
|
||||
)
|
||||
|
||||
#define TEGRA_CVT2PYUVTOBGR(src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx) \
|
||||
#define TEGRA_CVT2PYUVTOBGR_EX(y_data, y_step, uv_data, uv_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx) \
|
||||
( \
|
||||
CAROTENE_NS::isSupportedConfiguration() ? \
|
||||
dcn == 3 ? \
|
||||
uIdx == 0 ? \
|
||||
(swapBlue ? \
|
||||
CAROTENE_NS::yuv420i2rgb(CAROTENE_NS::Size2D(dst_width, dst_height), \
|
||||
src_data, src_step, \
|
||||
src_data + src_step * dst_height, src_step, \
|
||||
y_data, y_step, \
|
||||
uv_data, uv_step, \
|
||||
dst_data, dst_step) : \
|
||||
CAROTENE_NS::yuv420i2bgr(CAROTENE_NS::Size2D(dst_width, dst_height), \
|
||||
src_data, src_step, \
|
||||
src_data + src_step * dst_height, src_step, \
|
||||
y_data, y_step, \
|
||||
uv_data, uv_step, \
|
||||
dst_data, dst_step)), \
|
||||
CV_HAL_ERROR_OK : \
|
||||
uIdx == 1 ? \
|
||||
(swapBlue ? \
|
||||
CAROTENE_NS::yuv420sp2rgb(CAROTENE_NS::Size2D(dst_width, dst_height), \
|
||||
src_data, src_step, \
|
||||
src_data + src_step * dst_height, src_step, \
|
||||
y_data, y_step, \
|
||||
uv_data, uv_step, \
|
||||
dst_data, dst_step) : \
|
||||
CAROTENE_NS::yuv420sp2bgr(CAROTENE_NS::Size2D(dst_width, dst_height), \
|
||||
src_data, src_step, \
|
||||
src_data + src_step * dst_height, src_step, \
|
||||
y_data, y_step, \
|
||||
uv_data, uv_step, \
|
||||
dst_data, dst_step)), \
|
||||
CV_HAL_ERROR_OK : \
|
||||
CV_HAL_ERROR_NOT_IMPLEMENTED : \
|
||||
@@ -1809,29 +1809,32 @@ TegraCvtColor_Invoker(bgrx2hsvf, bgrx2hsv, src_data + static_cast<size_t>(range.
|
||||
uIdx == 0 ? \
|
||||
(swapBlue ? \
|
||||
CAROTENE_NS::yuv420i2rgbx(CAROTENE_NS::Size2D(dst_width, dst_height), \
|
||||
src_data, src_step, \
|
||||
src_data + src_step * dst_height, src_step, \
|
||||
y_data, y_step, \
|
||||
uv_data, uv_step, \
|
||||
dst_data, dst_step) : \
|
||||
CAROTENE_NS::yuv420i2bgrx(CAROTENE_NS::Size2D(dst_width, dst_height), \
|
||||
src_data, src_step, \
|
||||
src_data + src_step * dst_height, src_step, \
|
||||
y_data, y_step, \
|
||||
uv_data, uv_step, \
|
||||
dst_data, dst_step)), \
|
||||
CV_HAL_ERROR_OK : \
|
||||
uIdx == 1 ? \
|
||||
(swapBlue ? \
|
||||
CAROTENE_NS::yuv420sp2rgbx(CAROTENE_NS::Size2D(dst_width, dst_height), \
|
||||
src_data, src_step, \
|
||||
src_data + src_step * dst_height, src_step, \
|
||||
y_data, y_step, \
|
||||
uv_data, uv_step, \
|
||||
dst_data, dst_step) : \
|
||||
CAROTENE_NS::yuv420sp2bgrx(CAROTENE_NS::Size2D(dst_width, dst_height), \
|
||||
src_data, src_step, \
|
||||
src_data + src_step * dst_height, src_step, \
|
||||
y_data, y_step, \
|
||||
uv_data, uv_step, \
|
||||
dst_data, dst_step)), \
|
||||
CV_HAL_ERROR_OK : \
|
||||
CV_HAL_ERROR_NOT_IMPLEMENTED : \
|
||||
CV_HAL_ERROR_NOT_IMPLEMENTED \
|
||||
: CV_HAL_ERROR_NOT_IMPLEMENTED \
|
||||
)
|
||||
#define TEGRA_CVT2PYUVTOBGR(src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx) \
|
||||
TEGRA_CVT2PYUVTOBGR_EX(src_data, src_step, src_data + src_step * dst_height, src_step, dst_data, dst_step, \
|
||||
dst_width, dst_height, dcn, swapBlue, uIdx);
|
||||
|
||||
#undef cv_hal_cvtBGRtoBGR
|
||||
#define cv_hal_cvtBGRtoBGR TEGRA_CVTBGRTOBGR
|
||||
@@ -1841,12 +1844,18 @@ TegraCvtColor_Invoker(bgrx2hsvf, bgrx2hsv, src_data + static_cast<size_t>(range.
|
||||
#define cv_hal_cvtBGRtoGray TEGRA_CVTBGRTOGRAY
|
||||
#undef cv_hal_cvtGraytoBGR
|
||||
#define cv_hal_cvtGraytoBGR TEGRA_CVTGRAYTOBGR
|
||||
#if 0 // bit-exact tests are failed
|
||||
#undef cv_hal_cvtBGRtoYUV
|
||||
#define cv_hal_cvtBGRtoYUV TEGRA_CVTBGRTOYUV
|
||||
#endif
|
||||
#undef cv_hal_cvtBGRtoHSV
|
||||
#define cv_hal_cvtBGRtoHSV TEGRA_CVTBGRTOHSV
|
||||
#if 0 // bit-exact tests are failed
|
||||
#undef cv_hal_cvtTwoPlaneYUVtoBGR
|
||||
#define cv_hal_cvtTwoPlaneYUVtoBGR TEGRA_CVT2PYUVTOBGR
|
||||
#undef cv_hal_cvtTwoPlaneYUVtoBGREx
|
||||
#define cv_hal_cvtTwoPlaneYUVtoBGREx TEGRA_CVT2PYUVTOBGR_EX
|
||||
#endif
|
||||
|
||||
#endif // OPENCV_IMGPROC_HAL_INTERFACE_H
|
||||
|
||||
|
||||
Vendored
+5
-5
@@ -1,8 +1,8 @@
|
||||
# Binaries branch name: ffmpeg/master_20210608
|
||||
# Binaries were created for OpenCV: eaa9228a4fdfb9c2465aea65a50ce2d16b55dce0
|
||||
ocv_update(FFMPEG_BINARIES_COMMIT "213fcd5d4897319a83207406036c4a5957fba010")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN32 "bab661341c30862fa88627130219c0a5")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN64 "ac99f9767a83103c31709628af685924")
|
||||
# Binaries branch name: ffmpeg/4.x_20220524
|
||||
# Binaries were created for OpenCV: d6e9616256b46bd59be0a93d397f6ab958d39cd2
|
||||
ocv_update(FFMPEG_BINARIES_COMMIT "65ec04d4573dcdfa4531f0b9e67f35d8ffff873e")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN32 "5573e2262ad1298e603122b7759fc2f6")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN64 "5f9e2b2e04c15f080f40e844de80c867")
|
||||
ocv_update(FFMPEG_FILE_HASH_CMAKE "8862c87496e2e8c375965e1277dee1c7")
|
||||
|
||||
function(download_win_ffmpeg script_var)
|
||||
|
||||
Vendored
+1
@@ -54,6 +54,7 @@ set_target_properties(${ITT_LIBRARY} PROPERTIES
|
||||
)
|
||||
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wundef -Wsign-compare)
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wstrict-prototypes) # clang15
|
||||
|
||||
if(ENABLE_SOLUTION_FOLDERS)
|
||||
set_target_properties(${ITT_LIBRARY} PROPERTIES FOLDER "3rdparty")
|
||||
|
||||
+2
-2
@@ -4,9 +4,9 @@ ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter -Wsign-compare -Wshorten-6
|
||||
|
||||
set(VERSION_MAJOR 2)
|
||||
set(VERSION_MINOR 1)
|
||||
set(VERSION_REVISION 0)
|
||||
set(VERSION_REVISION 2)
|
||||
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION})
|
||||
set(LIBJPEG_TURBO_VERSION_NUMBER 2001000)
|
||||
set(LIBJPEG_TURBO_VERSION_NUMBER 2001002)
|
||||
|
||||
string(TIMESTAMP BUILD "opencv-${OPENCV_VERSION}-libjpeg-turbo")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
|
||||
+10
@@ -40,3 +40,13 @@
|
||||
#define HAVE_BITSCANFORWARD
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__has_attribute)
|
||||
#if __has_attribute(fallthrough)
|
||||
#define FALLTHROUGH __attribute__((fallthrough));
|
||||
#else
|
||||
#define FALLTHROUGH
|
||||
#endif
|
||||
#else
|
||||
#define FALLTHROUGH
|
||||
#endif
|
||||
|
||||
Vendored
+3
-2
@@ -44,8 +44,9 @@
|
||||
* flags (this defines __thumb__).
|
||||
*/
|
||||
|
||||
#if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || \
|
||||
defined(_M_ARM64)
|
||||
/* NOTE: Both GCC and Clang define __GNUC__ */
|
||||
#if (defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))) || \
|
||||
defined(_M_ARM) || defined(_M_ARM64)
|
||||
#if !defined(__thumb__) || defined(__thumb2__)
|
||||
#define USE_CLZ_INTRINSIC
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -493,7 +493,7 @@ prepare_for_pass(j_compress_ptr cinfo)
|
||||
master->pass_type = output_pass;
|
||||
master->pass_number++;
|
||||
#endif
|
||||
/*FALLTHROUGH*/
|
||||
FALLTHROUGH /*FALLTHROUGH*/
|
||||
case output_pass:
|
||||
/* Do a data-output pass. */
|
||||
/* We need not repeat per-scan setup if prior optimization pass did it. */
|
||||
|
||||
Vendored
+6
-4
@@ -7,6 +7,7 @@
|
||||
* Copyright (C) 2011, 2015, 2018, 2021, D. R. Commander.
|
||||
* Copyright (C) 2016, 2018, Matthieu Darbois.
|
||||
* Copyright (C) 2020, Arm Limited.
|
||||
* Copyright (C) 2021, Alex Richardson.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
@@ -52,8 +53,9 @@
|
||||
* flags (this defines __thumb__).
|
||||
*/
|
||||
|
||||
#if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || \
|
||||
defined(_M_ARM64)
|
||||
/* NOTE: Both GCC and Clang define __GNUC__ */
|
||||
#if (defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))) || \
|
||||
defined(_M_ARM) || defined(_M_ARM64)
|
||||
#if !defined(__thumb__) || defined(__thumb2__)
|
||||
#define USE_CLZ_INTRINSIC
|
||||
#endif
|
||||
@@ -679,7 +681,7 @@ encode_mcu_AC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
emit_restart(entropy, entropy->next_restart_num);
|
||||
|
||||
#ifdef WITH_SIMD
|
||||
cvalue = values = (JCOEF *)PAD((size_t)values_unaligned, 16);
|
||||
cvalue = values = (JCOEF *)PAD((JUINTPTR)values_unaligned, 16);
|
||||
#else
|
||||
/* Not using SIMD, so alignment is not needed */
|
||||
cvalue = values = values_unaligned;
|
||||
@@ -944,7 +946,7 @@ encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
emit_restart(entropy, entropy->next_restart_num);
|
||||
|
||||
#ifdef WITH_SIMD
|
||||
cabsvalue = absvalues = (JCOEF *)PAD((size_t)absvalues_unaligned, 16);
|
||||
cabsvalue = absvalues = (JCOEF *)PAD((JUINTPTR)absvalues_unaligned, 16);
|
||||
#else
|
||||
/* Not using SIMD, so alignment is not needed */
|
||||
cabsvalue = absvalues = absvalues_unaligned;
|
||||
|
||||
+2
-1
@@ -23,6 +23,7 @@
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jdmaster.h"
|
||||
#include "jconfigint.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -308,7 +309,7 @@ jpeg_consume_input(j_decompress_ptr cinfo)
|
||||
/* Initialize application's data source module */
|
||||
(*cinfo->src->init_source) (cinfo);
|
||||
cinfo->global_state = DSTATE_INHEADER;
|
||||
/*FALLTHROUGH*/
|
||||
FALLTHROUGH /*FALLTHROUGH*/
|
||||
case DSTATE_INHEADER:
|
||||
retcode = (*cinfo->inputctl->consume_input) (cinfo);
|
||||
if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */
|
||||
|
||||
Vendored
+10
-1
@@ -584,7 +584,7 @@ decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
* behavior is, to the best of our understanding, innocuous, and it is
|
||||
* unclear how to work around it without potentially affecting
|
||||
* performance. Thus, we (hopefully temporarily) suppress UBSan integer
|
||||
* overflow errors for this function.
|
||||
* overflow errors for this function and decode_mcu_fast().
|
||||
*/
|
||||
s += state.last_dc_val[ci];
|
||||
state.last_dc_val[ci] = s;
|
||||
@@ -651,6 +651,12 @@ decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
}
|
||||
|
||||
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(undefined_behavior_sanitizer)
|
||||
__attribute__((no_sanitize("signed-integer-overflow"),
|
||||
no_sanitize("unsigned-integer-overflow")))
|
||||
#endif
|
||||
#endif
|
||||
LOCAL(boolean)
|
||||
decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
@@ -681,6 +687,9 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
|
||||
if (entropy->dc_needed[blkn]) {
|
||||
int ci = cinfo->MCU_membership[blkn];
|
||||
/* Refer to the comment in decode_mcu_slow() regarding the supression of
|
||||
* a UBSan integer overflow error in this line of code.
|
||||
*/
|
||||
s += state.last_dc_val[ci];
|
||||
state.last_dc_val[ci] = s;
|
||||
if (block)
|
||||
|
||||
+3
-2
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "jinclude.h"
|
||||
#include "jdmainct.h"
|
||||
#include "jconfigint.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -360,7 +361,7 @@ process_data_context_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf,
|
||||
main_ptr->context_state = CTX_PREPARE_FOR_IMCU;
|
||||
if (*out_row_ctr >= out_rows_avail)
|
||||
return; /* Postprocessor exactly filled output buf */
|
||||
/*FALLTHROUGH*/
|
||||
FALLTHROUGH /*FALLTHROUGH*/
|
||||
case CTX_PREPARE_FOR_IMCU:
|
||||
/* Prepare to process first M-1 row groups of this iMCU row */
|
||||
main_ptr->rowgroup_ctr = 0;
|
||||
@@ -371,7 +372,7 @@ process_data_context_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf,
|
||||
if (main_ptr->iMCU_row_ctr == cinfo->total_iMCU_rows)
|
||||
set_bottom_pointers(cinfo);
|
||||
main_ptr->context_state = CTX_PROCESS_IMCU;
|
||||
/*FALLTHROUGH*/
|
||||
FALLTHROUGH /*FALLTHROUGH*/
|
||||
case CTX_PROCESS_IMCU:
|
||||
/* Call postprocessor using previously set pointers */
|
||||
(*cinfo->post->post_process_data) (cinfo,
|
||||
|
||||
Vendored
+3
-3
@@ -4,7 +4,7 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2016, D. R. Commander.
|
||||
* Copyright (C) 2016, 2021, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
@@ -1032,7 +1032,7 @@ free_pool(j_common_ptr cinfo, int pool_id)
|
||||
large_pool_ptr next_lhdr_ptr = lhdr_ptr->next;
|
||||
space_freed = lhdr_ptr->bytes_used +
|
||||
lhdr_ptr->bytes_left +
|
||||
sizeof(large_pool_hdr);
|
||||
sizeof(large_pool_hdr) + ALIGN_SIZE - 1;
|
||||
jpeg_free_large(cinfo, (void *)lhdr_ptr, space_freed);
|
||||
mem->total_space_allocated -= space_freed;
|
||||
lhdr_ptr = next_lhdr_ptr;
|
||||
@@ -1045,7 +1045,7 @@ free_pool(j_common_ptr cinfo, int pool_id)
|
||||
while (shdr_ptr != NULL) {
|
||||
small_pool_ptr next_shdr_ptr = shdr_ptr->next;
|
||||
space_freed = shdr_ptr->bytes_used + shdr_ptr->bytes_left +
|
||||
sizeof(small_pool_hdr);
|
||||
sizeof(small_pool_hdr) + ALIGN_SIZE - 1;
|
||||
jpeg_free_small(cinfo, (void *)shdr_ptr, space_freed);
|
||||
mem->total_space_allocated -= space_freed;
|
||||
shdr_ptr = next_shdr_ptr;
|
||||
|
||||
Vendored
+14
-1
@@ -5,8 +5,9 @@
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 1997-2009 by Guido Vollbeding.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2015-2016, 2019, D. R. Commander.
|
||||
* Copyright (C) 2015-2016, 2019, 2021, D. R. Commander.
|
||||
* Copyright (C) 2015, Google, Inc.
|
||||
* Copyright (C) 2021, Alex Richardson.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
@@ -47,6 +48,18 @@ typedef enum { /* Operating modes for buffer controllers */
|
||||
/* JLONG must hold at least signed 32-bit values. */
|
||||
typedef long JLONG;
|
||||
|
||||
/* JUINTPTR must hold pointer values. */
|
||||
#ifdef __UINTPTR_TYPE__
|
||||
/*
|
||||
* __UINTPTR_TYPE__ is GNU-specific and available in GCC 4.6+ and Clang 3.0+.
|
||||
* Fortunately, that is sufficient to support the few architectures for which
|
||||
* sizeof(void *) != sizeof(size_t). The only other options would require C99
|
||||
* or Clang-specific builtins.
|
||||
*/
|
||||
typedef __UINTPTR_TYPE__ JUINTPTR;
|
||||
#else
|
||||
typedef size_t JUINTPTR;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Left shift macro that handles a negative operand without causing any
|
||||
|
||||
Vendored
+5
-1
@@ -77,7 +77,11 @@ endif(MSVC)
|
||||
add_library(${PNG_LIBRARY} STATIC ${OPENCV_3RDPARTY_EXCLUDE_FROM_ALL} ${lib_srcs} ${lib_hdrs})
|
||||
target_link_libraries(${PNG_LIBRARY} ${ZLIB_LIBRARIES})
|
||||
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wundef -Wcast-align -Wimplicit-fallthrough -Wunused-parameter -Wsign-compare)
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wundef -Wcast-align -Wimplicit-fallthrough -Wunused-parameter -Wsign-compare
|
||||
-Wmaybe-uninitialized
|
||||
-Wnull-pointer-subtraction # clang15
|
||||
-Wunused-but-set-variable # clang15
|
||||
)
|
||||
|
||||
set_target_properties(${PNG_LIBRARY}
|
||||
PROPERTIES OUTPUT_NAME ${PNG_LIBRARY}
|
||||
|
||||
Vendored
+3
-1
@@ -452,8 +452,10 @@ ocv_warnings_disable(CMAKE_C_FLAGS -Wno-unused-but-set-variable -Wmissing-protot
|
||||
-Wcast-align -Wshadow -Wno-maybe-uninitialized -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast
|
||||
-Wmisleading-indentation
|
||||
-Wimplicit-fallthrough
|
||||
-Wunused-parameter # clang
|
||||
-Warray-parameter
|
||||
-Wstrict-prototypes # clang15
|
||||
)
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter) # clang
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wmissing-declarations -Wunused-parameter -Wmissing-prototypes
|
||||
-Wundef # tiffiop.h: #if __clang_major__ >= 4
|
||||
)
|
||||
|
||||
Vendored
+73
@@ -0,0 +1,73 @@
|
||||
set(TIMVX_COMMIT_HASH "1d9c7ab941b3d8d9c4d28d80058402725731e3d6")
|
||||
set(OCV_TIMVX_DIR "${OpenCV_BINARY_DIR}/3rdparty/libtim-vx")
|
||||
set(OCV_TIMVX_SOURCE_PATH "${OCV_TIMVX_DIR}/TIM-VX-${TIMVX_COMMIT_HASH}")
|
||||
|
||||
# Download TIM-VX source code
|
||||
if(EXISTS "${OCV_TIMVX_SOURCE_PATH}")
|
||||
message(STATUS "TIM-VX: Use cache of TIM-VX source code at ${OCV_TIMVX_SOURCE_PATH}")
|
||||
set(TIMVX_FOUND ON)
|
||||
else()
|
||||
set(OCV_TIMVX_FILENAME "${TIMVX_COMMIT_HASH}.zip")
|
||||
set(OCV_TIMVX_URL "https://github.com/VeriSilicon/TIM-VX/archive/")
|
||||
set(timvx_zip_md5sum 92619cc4498014ac7a09834d5e33ebd5)
|
||||
|
||||
ocv_download(FILENAME ${OCV_TIMVX_FILENAME}
|
||||
HASH ${timvx_zip_md5sum}
|
||||
URL "${OCV_TIMVX_URL}"
|
||||
DESTINATION_DIR "${OCV_TIMVX_DIR}"
|
||||
ID "TIM-VX"
|
||||
STATUS res
|
||||
UNPACK RELATIVE_URL)
|
||||
if(res)
|
||||
set(TIMVX_FOUND ON)
|
||||
message(STATUS "TIM-VX: Source code downloaded at ${OCV_TIMVX_SOURCE_PATH}.")
|
||||
else()
|
||||
set(TIMVX_FOUND OFF)
|
||||
message(STATUS "TIM-VX: Failed to download source code from github. Turning off TIMVX_FOUND")
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# set VIVANTE SDK especially for x86_64 which comes along with TIM-VX source code
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64)
|
||||
set(VIVANTE_SDK_DIR "${OCV_TIMVX_SOURCE_PATH}/prebuilt-sdk/x86_64_linux")
|
||||
message(STATUS "TIM-VX: Build from source using prebuilt x86_64 VIVANTE SDK.")
|
||||
endif()
|
||||
|
||||
# Verify if requested VIVANTE SDK libraries are all found
|
||||
find_vivante_sdk_libs(missing ${VIVANTE_SDK_DIR})
|
||||
if(missing)
|
||||
message(STATUS "TIM-VX: Failed to find ${missing} in ${VIVANTE_SDK_DIR}/lib. Turning off TIMVX_VIV_FOUND")
|
||||
set(TIMVX_VIV_FOUND OFF)
|
||||
else()
|
||||
message(STATUS "TIM-VX: dependent VIVANTE SDK libraries are found at ${VIVANTE_SDK_DIR}/lib.")
|
||||
set(TIMVX_VIV_FOUND ON)
|
||||
endif()
|
||||
|
||||
if(TIMVX_VIV_FOUND)
|
||||
# vars used by TIM-VX CMake scripts
|
||||
set(EXTERNAL_VIV_SDK "${VIVANTE_SDK_DIR}" CACHE INTERNAL "" FORCE)
|
||||
set(VIV_SDK_DRIVER_PREFIX "lib" CACHE INTERNAL "" FORCE)
|
||||
endif()
|
||||
|
||||
if(TIMVX_FOUND AND TIMVX_VIV_FOUND)
|
||||
set(BUILD_TIMVX ON)
|
||||
else()
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(BUILD_TIMVX)
|
||||
set(HAVE_TIMVX 1)
|
||||
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter -Wstrict-prototypes -Wundef -Wsign-compare -Wmissing-prototypes -Wmissing-declarations -Wstrict-aliasing -Wunused-but-set-variable -Wmaybe-uninitialized -Wshadow -Wsuggest-override -Wswitch)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wunused-parameter -Wstrict-prototypes -Wundef -Wsign-compare -Wunused-but-set-variable -Wshadow -Wsuggest-override -Wmissing-declarations -Wswitch)
|
||||
|
||||
set(TIMVX_INC_DIR "${OCV_TIMVX_SOURCE_PATH}/include" CACHE INTERNAL "TIM-VX include directory")
|
||||
if(EXISTS "${OCV_TIMVX_SOURCE_PATH}/CMakeLists.txt")
|
||||
add_subdirectory("${OCV_TIMVX_SOURCE_PATH}" "${OCV_TIMVX_DIR}/build")
|
||||
else()
|
||||
message(WARNING "TIM-VX: Missing 'CMakeLists.txt' in the source code: ${OCV_TIMVX_SOURCE_PATH}")
|
||||
endif()
|
||||
ocv_install_target(tim-vx EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev)
|
||||
set(TIMVX_LIB "tim-vx")
|
||||
endif()
|
||||
Vendored
+4
-1
@@ -32,7 +32,9 @@ endif()
|
||||
# Define the library target:
|
||||
# ----------------------------------------------------------------------------------
|
||||
|
||||
add_definitions(-DWEBP_USE_THREAD)
|
||||
if(NOT OPENCV_DISABLE_THREAD_SUPPORT)
|
||||
add_definitions(-DWEBP_USE_THREAD)
|
||||
endif()
|
||||
|
||||
add_library(${WEBP_LIBRARY} STATIC ${OPENCV_3RDPARTY_EXCLUDE_FROM_ALL} ${lib_srcs} ${lib_hdrs})
|
||||
if(ANDROID)
|
||||
@@ -43,6 +45,7 @@ ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-variable -Wunused-function -Wshadow
|
||||
-Wmissing-prototypes # clang
|
||||
-Wmissing-declarations # gcc
|
||||
-Wimplicit-fallthrough
|
||||
-Wunused-but-set-variable # clang15
|
||||
)
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS /wd4244 /wd4267) # vs2005
|
||||
|
||||
|
||||
Vendored
+1
@@ -13,6 +13,7 @@ project(openjpeg C)
|
||||
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS
|
||||
-Wimplicit-const-int-float-conversion # clang
|
||||
-Wunused-but-set-variable # clang15
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
Vendored
+1
-1
@@ -77,7 +77,7 @@ E.g. external ref-counting is implemented for 1.0 version and native OpenVX one
|
||||
|
||||
Also there are some **C++ 11** features are used (e.g. rvalue ref-s) when their availability is detected at ***compile time***.
|
||||
|
||||
C++ exceptions are used for errors indication instead of return codes. There are two types of exceptions are defined: `RuntimeError` is thrown when OpenVX C call returned unsuccessful result and `WrapperError` is thrown when a problem is occured in the wrappers code. Both exception calsses are derived from `std::exception` (actually from its inheritants).
|
||||
C++ exceptions are used for errors indication instead of return codes. There are two types of exceptions are defined: `RuntimeError` is thrown when OpenVX C call returned unsuccessful result and `WrapperError` is thrown when a problem is occurred in the wrappers code. Both exception calsses are derived from `std::exception` (actually from its inheritants).
|
||||
|
||||
The so called **OpenVX objects** (e.g. `vx_image`) are represented as C++ classes in wrappers.
|
||||
All these classes use automatic ref-counting that allows development of exception-safe code.
|
||||
|
||||
Vendored
+9
-5
@@ -923,6 +923,11 @@ int ovx_hal_cvtGraytoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep,
|
||||
}
|
||||
|
||||
int ovx_hal_cvtTwoPlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx)
|
||||
{
|
||||
return ovx_hal_cvtTwoPlaneYUVtoBGREx(a, astep, a + h * astep, astep, b, bstep, w, h, bcn, swapBlue, uIdx);
|
||||
}
|
||||
|
||||
int ovx_hal_cvtTwoPlaneYUVtoBGREx(const uchar * a, size_t astep, const uchar * b, size_t bstep, uchar * c, size_t cstep, int w, int h, int bcn, bool swapBlue, int uIdx)
|
||||
{
|
||||
if (skipSmallImages<VX_KERNEL_COLOR_CONVERT>(w, h))
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
@@ -933,8 +938,7 @@ int ovx_hal_cvtTwoPlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t
|
||||
|
||||
if (w & 1 || h & 1) // It's not described in spec but sample implementation unable to convert odd sized images
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
refineStep(w, h, uIdx ? VX_DF_IMAGE_NV21 : VX_DF_IMAGE_NV12, astep);
|
||||
refineStep(w, h, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, bstep);
|
||||
|
||||
try
|
||||
{
|
||||
ivx::Context ctx = getOpenVXHALContext();
|
||||
@@ -943,8 +947,8 @@ int ovx_hal_cvtTwoPlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t
|
||||
std::vector<void *> ptrs;
|
||||
addr.push_back(ivx::Image::createAddressing(w, h, 1, (vx_int32)astep));
|
||||
ptrs.push_back((void*)a);
|
||||
addr.push_back(ivx::Image::createAddressing(w / 2, h / 2, 2, (vx_int32)astep));
|
||||
ptrs.push_back((void*)(a + h * astep));
|
||||
addr.push_back(ivx::Image::createAddressing(w / 2, h / 2, 2, (vx_int32)bstep));
|
||||
ptrs.push_back((void*)b);
|
||||
|
||||
vxImage
|
||||
ia = ivx::Image::createFromHandle(ctx, uIdx ? VX_DF_IMAGE_NV21 : VX_DF_IMAGE_NV12, addr, ptrs);
|
||||
@@ -952,7 +956,7 @@ int ovx_hal_cvtTwoPlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED; // OpenCV store NV12/NV21 as RANGE_RESTRICTED while OpenVX expect RANGE_FULL
|
||||
vxImage
|
||||
ib = ivx::Image::createFromHandle(ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX,
|
||||
ivx::Image::createAddressing(w, h, bcn, (vx_int32)bstep), b);
|
||||
ivx::Image::createAddressing(w, h, bcn, (vx_int32)cstep), c);
|
||||
ivx::IVX_CHECK_STATUS(vxuColorConvert(ctx, ia, ib));
|
||||
}
|
||||
catch (ivx::RuntimeError & e)
|
||||
|
||||
Vendored
+3
@@ -49,6 +49,7 @@ int ovx_hal_morph(cvhalFilter2D *filter_context, uchar *a, size_t astep, uchar *
|
||||
int ovx_hal_cvtBGRtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int depth, int acn, int bcn, bool swapBlue);
|
||||
int ovx_hal_cvtGraytoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int depth, int bcn);
|
||||
int ovx_hal_cvtTwoPlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx);
|
||||
int ovx_hal_cvtTwoPlaneYUVtoBGREx(const uchar * a, size_t astep, const uchar * b, size_t bstep, uchar * c, size_t cstep, int w, int h, int bcn, bool swapBlue, int uIdx);
|
||||
int ovx_hal_cvtThreePlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx);
|
||||
int ovx_hal_cvtBGRtoThreePlaneYUV(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int acn, bool swapBlue, int uIdx);
|
||||
int ovx_hal_cvtOnePlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx, int ycn);
|
||||
@@ -130,6 +131,8 @@ int ovx_hal_integral(int depth, int sdepth, int, const uchar * a, size_t astep,
|
||||
#define cv_hal_cvtGraytoBGR ovx_hal_cvtGraytoBGR
|
||||
#undef cv_hal_cvtTwoPlaneYUVtoBGR
|
||||
#define cv_hal_cvtTwoPlaneYUVtoBGR ovx_hal_cvtTwoPlaneYUVtoBGR
|
||||
#undef cv_hal_cvtTwoPlaneYUVtoBGREx
|
||||
#define cv_hal_cvtTwoPlaneYUVtoBGREx ovx_hal_cvtTwoPlaneYUVtoBGREx
|
||||
#undef cv_hal_cvtThreePlaneYUVtoBGR
|
||||
#define cv_hal_cvtThreePlaneYUVtoBGR ovx_hal_cvtThreePlaneYUVtoBGR
|
||||
#undef cv_hal_cvtBGRtoThreePlaneYUV
|
||||
|
||||
Vendored
+56
-50
@@ -13,6 +13,9 @@ if(MSVC)
|
||||
/wd4701 /wd4703 # potentially uninitialized local/pointer variable 'value' used
|
||||
/wd4505 # unreferenced local function has been removed
|
||||
)
|
||||
if(MSVC_VERSION LESS 1920) # MSVS 2015/2017
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4309) # 'static_cast': truncation of constant value
|
||||
endif()
|
||||
else()
|
||||
#NOTE: -Wno-invalid-offsetof was used as solution for invalid offset warning on protobuf #3450
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-deprecated -Wmissing-prototypes -Wmissing-declarations -Wshadow
|
||||
@@ -49,98 +52,101 @@ endfunction()
|
||||
|
||||
set(PROTOBUF_ROOT "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
if(MSVC)
|
||||
set(ATOMICOPS_INTERNALS ${PROTOBUF_ROOT}/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc)
|
||||
else()
|
||||
set(ATOMICOPS_INTERNALS ${PROTOBUF_ROOT}/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc)
|
||||
endif()
|
||||
|
||||
|
||||
append_if_exist(Protobuf_SRCS
|
||||
# libprotobuf-lite
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/any_lite.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/arena.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/arenastring.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/extension_set.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/generated_message_table_driven_lite.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/generated_enum_util.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/generated_message_table_driven_lite.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/generated_message_tctable_lite.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/generated_message_util.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/implicit_weak_message.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/inlined_string_field.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/io/coded_stream.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/io/io_win32.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/io/strtod.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/io/zero_copy_stream.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/io/zero_copy_stream_impl.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/map.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/message_lite.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/parse_context.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/repeated_field.cc
|
||||
${ATOMICOPS_INTERNALS}
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/repeated_ptr_field.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/stubs/bytestream.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/stubs/common.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/stubs/int128.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/stubs/io_win32.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/stubs/once.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/stubs/status.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/stubs/statusor.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/stubs/statusor.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/stubs/stringpiece.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/stubs/stringprintf.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/stubs/structurally_valid.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/stubs/strutil.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/stubs/time.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/stubs/time.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/wire_format_lite.cc
|
||||
|
||||
# libprotobuf
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/any.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/any.pb.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/api.pb.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/any.pb.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/api.pb.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/compiler/importer.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/compiler/parser.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/descriptor.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/descriptor.pb.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/descriptor_database.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/duration.pb.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/duration.pb.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/dynamic_message.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/empty.pb.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/empty.pb.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/extension_set_heavy.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/field_mask.pb.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/field_mask.pb.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/generated_message_bases.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/generated_message_reflection.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/generated_message_table_driven.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/io/gzip_stream.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/io/printer.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/io/strtod.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/generated_message_table_driven.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/generated_message_tctable_full.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/io/gzip_stream.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/io/printer.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/io/tokenizer.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/io/zero_copy_stream_impl.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/map_field.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/message.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/reflection_ops.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/service.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/source_context.pb.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/struct.pb.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/stubs/mathlimits.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/service.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/source_context.pb.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/struct.pb.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/stubs/substitute.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/text_format.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/timestamp.pb.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/type.pb.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/timestamp.pb.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/type.pb.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/unknown_field_set.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/delimited_message_util.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/field_comparator.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/field_mask_util.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/internal/datapiece.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/internal/default_value_objectwriter.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/delimited_message_util.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/field_comparator.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/field_mask_util.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/internal/datapiece.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/internal/default_value_objectwriter.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/internal/error_listener.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/internal/field_mask_utility.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/internal/json_escaping.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/internal/json_objectwriter.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/internal/json_stream_parser.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/internal/object_writer.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/internal/proto_writer.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/internal/protostream_objectsource.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/internal/protostream_objectwriter.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/internal/type_info.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/internal/type_info_test_helper.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/internal/utility.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/json_util.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/message_differencer.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/time_util.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/util/type_resolver_util.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/internal/field_mask_utility.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/internal/json_escaping.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/internal/json_objectwriter.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/internal/json_stream_parser.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/internal/object_writer.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/internal/proto_writer.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/internal/protostream_objectsource.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/internal/protostream_objectwriter.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/internal/type_info.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/internal/utility.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/json_util.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/message_differencer.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/time_util.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/util/type_resolver_util.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/wire_format.cc
|
||||
${PROTOBUF_ROOT}/src/google/protobuf/wrappers.pb.cc
|
||||
# ${PROTOBUF_ROOT}/src/google/protobuf/wrappers.pb.cc
|
||||
)
|
||||
|
||||
include_directories(BEFORE "${PROTOBUF_ROOT}/src") # ensure using if own headers: https://github.com/opencv/opencv/issues/13328
|
||||
|
||||
include_directories(BEFORE "${PROTOBUF_ROOT}/src") # ensure using of own headers: https://github.com/opencv/opencv/issues/13328
|
||||
|
||||
add_library(libprotobuf STATIC ${OPENCV_3RDPARTY_EXCLUDE_FROM_ALL} ${Protobuf_SRCS})
|
||||
target_include_directories(libprotobuf SYSTEM PUBLIC $<BUILD_INTERFACE:${PROTOBUF_ROOT}/src>)
|
||||
set_target_properties(libprotobuf
|
||||
|
||||
Vendored
+1
-11
@@ -1,14 +1,4 @@
|
||||
This license applies to all parts of Protocol Buffers except the following:
|
||||
|
||||
- Atomicops support for generic gcc, located in
|
||||
src/google/protobuf/stubs/atomicops_internals_generic_gcc.h.
|
||||
This file is copyrighted by Red Hat Inc.
|
||||
|
||||
- Atomicops support for AIX/POWER, located in
|
||||
src/google/protobuf/stubs/atomicops_internals_power.h.
|
||||
This file is copyrighted by Bloomberg Finance LP.
|
||||
|
||||
Copyright 2014, Google Inc. All rights reserved.
|
||||
Copyright 2008 Google Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
|
||||
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
||||
Project: Protocol Buffers - Google's data interchange format
|
||||
Source code: https://github.com/protocolbuffers/protobuf
|
||||
Version: 3.5.2
|
||||
Version: 3.19.1
|
||||
|
||||
+28
-59
@@ -30,85 +30,54 @@
|
||||
|
||||
#include <google/protobuf/any.h>
|
||||
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/message.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
namespace {
|
||||
string GetTypeUrl(const Descriptor* message,
|
||||
const string& type_url_prefix) {
|
||||
if (!type_url_prefix.empty() &&
|
||||
type_url_prefix[type_url_prefix.size() - 1] == '/') {
|
||||
return type_url_prefix + message->full_name();
|
||||
} else {
|
||||
return type_url_prefix + "/" + message->full_name();
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
const char kAnyFullTypeName[] = "google.protobuf.Any";
|
||||
const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/";
|
||||
const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/";
|
||||
|
||||
AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value)
|
||||
: type_url_(type_url), value_(value) {
|
||||
bool AnyMetadata::PackFrom(Arena* arena, const Message& message) {
|
||||
return PackFrom(arena, message, kTypeGoogleApisComPrefix);
|
||||
}
|
||||
|
||||
void AnyMetadata::PackFrom(const Message& message) {
|
||||
PackFrom(message, kTypeGoogleApisComPrefix);
|
||||
}
|
||||
|
||||
void AnyMetadata::PackFrom(const Message& message,
|
||||
const string& type_url_prefix) {
|
||||
type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(),
|
||||
GetTypeUrl(message.GetDescriptor(), type_url_prefix));
|
||||
message.SerializeToString(value_->MutableNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
|
||||
bool AnyMetadata::PackFrom(Arena* arena, const Message& message,
|
||||
StringPiece type_url_prefix) {
|
||||
type_url_->Set(
|
||||
&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString(),
|
||||
GetTypeUrl(message.GetDescriptor()->full_name(), type_url_prefix), arena);
|
||||
return message.SerializeToString(
|
||||
value_->Mutable(ArenaStringPtr::EmptyDefault{}, arena));
|
||||
}
|
||||
|
||||
bool AnyMetadata::UnpackTo(Message* message) const {
|
||||
if (!InternalIs(message->GetDescriptor())) {
|
||||
if (!InternalIs(message->GetDescriptor()->full_name())) {
|
||||
return false;
|
||||
}
|
||||
return message->ParseFromString(value_->GetNoArena());
|
||||
return message->ParseFromString(value_->Get());
|
||||
}
|
||||
|
||||
bool AnyMetadata::InternalIs(const Descriptor* descriptor) const {
|
||||
const string type_url = type_url_->GetNoArena();
|
||||
string full_name;
|
||||
if (!ParseAnyTypeUrl(type_url, &full_name)) {
|
||||
return false;
|
||||
}
|
||||
return full_name == descriptor->full_name();
|
||||
}
|
||||
|
||||
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
|
||||
size_t pos = type_url.find_last_of("/");
|
||||
if (pos == string::npos || pos + 1 == type_url.size()) {
|
||||
return false;
|
||||
}
|
||||
*full_type_name = type_url.substr(pos + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool GetAnyFieldDescriptors(const Message& message,
|
||||
const FieldDescriptor** type_url_field,
|
||||
const FieldDescriptor** value_field) {
|
||||
const Descriptor* descriptor = message.GetDescriptor();
|
||||
if (descriptor->full_name() != kAnyFullTypeName) {
|
||||
return false;
|
||||
}
|
||||
*type_url_field = descriptor->FindFieldByNumber(1);
|
||||
*value_field = descriptor->FindFieldByNumber(2);
|
||||
return (*type_url_field != NULL &&
|
||||
(*type_url_field)->type() == FieldDescriptor::TYPE_STRING &&
|
||||
*value_field != NULL &&
|
||||
(*value_field)->type() == FieldDescriptor::TYPE_BYTES);
|
||||
const Descriptor* descriptor = message.GetDescriptor();
|
||||
if (descriptor->full_name() != kAnyFullTypeName) {
|
||||
return false;
|
||||
}
|
||||
*type_url_field = descriptor->FindFieldByNumber(1);
|
||||
*value_field = descriptor->FindFieldByNumber(2);
|
||||
return (*type_url_field != nullptr &&
|
||||
(*type_url_field)->type() == FieldDescriptor::TYPE_STRING &&
|
||||
*value_field != nullptr &&
|
||||
(*value_field)->type() == FieldDescriptor::TYPE_BYTES);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
+66
-17
@@ -34,49 +34,89 @@
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class FieldDescriptor;
|
||||
class Message;
|
||||
|
||||
namespace internal {
|
||||
|
||||
extern const char kAnyFullTypeName[]; // "google.protobuf.Any".
|
||||
extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/".
|
||||
extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/".
|
||||
|
||||
std::string GetTypeUrl(StringPiece message_name,
|
||||
StringPiece type_url_prefix);
|
||||
|
||||
// Helper class used to implement google::protobuf::Any.
|
||||
class LIBPROTOBUF_EXPORT AnyMetadata {
|
||||
class PROTOBUF_EXPORT AnyMetadata {
|
||||
typedef ArenaStringPtr UrlType;
|
||||
typedef ArenaStringPtr ValueType;
|
||||
public:
|
||||
// AnyMetadata does not take ownership of "type_url" and "value".
|
||||
AnyMetadata(UrlType* type_url, ValueType* value);
|
||||
constexpr AnyMetadata(UrlType* type_url, ValueType* value)
|
||||
: type_url_(type_url), value_(value) {}
|
||||
|
||||
// Packs a message using the default type URL prefix: "type.googleapis.com".
|
||||
// The resulted type URL will be "type.googleapis.com/<message_full_name>".
|
||||
void PackFrom(const Message& message);
|
||||
// Returns false if serializing the message failed.
|
||||
template <typename T>
|
||||
bool PackFrom(Arena* arena, const T& message) {
|
||||
return InternalPackFrom(arena, message, kTypeGoogleApisComPrefix,
|
||||
T::FullMessageName());
|
||||
}
|
||||
|
||||
bool PackFrom(Arena* arena, const Message& message);
|
||||
|
||||
// Packs a message using the given type URL prefix. The type URL will be
|
||||
// constructed by concatenating the message type's full name to the prefix
|
||||
// with an optional "/" separator if the prefix doesn't already end up "/".
|
||||
// with an optional "/" separator if the prefix doesn't already end with "/".
|
||||
// For example, both PackFrom(message, "type.googleapis.com") and
|
||||
// PackFrom(message, "type.googleapis.com/") yield the same result type
|
||||
// URL: "type.googleapis.com/<message_full_name>".
|
||||
void PackFrom(const Message& message, const string& type_url_prefix);
|
||||
// Returns false if serializing the message failed.
|
||||
template <typename T>
|
||||
bool PackFrom(Arena* arena, const T& message,
|
||||
StringPiece type_url_prefix) {
|
||||
return InternalPackFrom(arena, message, type_url_prefix,
|
||||
T::FullMessageName());
|
||||
}
|
||||
|
||||
bool PackFrom(Arena* arena, const Message& message,
|
||||
StringPiece type_url_prefix);
|
||||
|
||||
// Unpacks the payload into the given message. Returns false if the message's
|
||||
// type doesn't match the type specified in the type URL (i.e., the full
|
||||
// name after the last "/" of the type URL doesn't match the message's actual
|
||||
// full name) or parsing the payload has failed.
|
||||
template <typename T>
|
||||
bool UnpackTo(T* message) const {
|
||||
return InternalUnpackTo(T::FullMessageName(), message);
|
||||
}
|
||||
|
||||
bool UnpackTo(Message* message) const;
|
||||
|
||||
// Checks whether the type specified in the type URL matches the given type.
|
||||
// A type is consdiered matching if its full name matches the full name after
|
||||
// A type is considered matching if its full name matches the full name after
|
||||
// the last "/" in the type URL.
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
bool Is() const {
|
||||
return InternalIs(T::default_instance().GetDescriptor());
|
||||
return InternalIs(T::FullMessageName());
|
||||
}
|
||||
|
||||
private:
|
||||
bool InternalIs(const Descriptor* message) const;
|
||||
bool InternalPackFrom(Arena* arena, const MessageLite& message,
|
||||
StringPiece type_url_prefix,
|
||||
StringPiece type_name);
|
||||
bool InternalUnpackTo(StringPiece type_name,
|
||||
MessageLite* message) const;
|
||||
bool InternalIs(StringPiece type_name) const;
|
||||
|
||||
UrlType* type_url_;
|
||||
ValueType* value_;
|
||||
@@ -84,15 +124,22 @@ class LIBPROTOBUF_EXPORT AnyMetadata {
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata);
|
||||
};
|
||||
|
||||
extern const char kAnyFullTypeName[]; // "google.protobuf.Any".
|
||||
extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/".
|
||||
extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/".
|
||||
|
||||
// Get the proto type name from Any::type_url value. For example, passing
|
||||
// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in
|
||||
// *full_type_name. Returns false if the type_url does not have a "/"
|
||||
// in the type url separating the full type name.
|
||||
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name);
|
||||
//
|
||||
// NOTE: this function is available publicly as:
|
||||
// google::protobuf::Any() // static method on the generated message type.
|
||||
bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name);
|
||||
|
||||
// Get the proto type name and prefix from Any::type_url value. For example,
|
||||
// passing "type.googleapis.com/rpc.QueryOrigin" will return
|
||||
// "type.googleapis.com/" in *url_prefix and "rpc.QueryOrigin" in
|
||||
// *full_type_name. Returns false if the type_url does not have a "/" in the
|
||||
// type url separating the full type name.
|
||||
bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
|
||||
std::string* full_type_name);
|
||||
|
||||
// See if message is of type google.protobuf.Any, if so, return the descriptors
|
||||
// for "type_url" and "value" fields.
|
||||
@@ -102,6 +149,8 @@ bool GetAnyFieldDescriptors(const Message& message,
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ANY_H__
|
||||
|
||||
-440
@@ -1,440 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/any.proto
|
||||
|
||||
#include <google/protobuf/any.pb.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// This is a temporary google only hack
|
||||
#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
|
||||
#include "third_party/protobuf/version.h"
|
||||
#endif
|
||||
// @@protoc_insertion_point(includes)
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class AnyDefaultTypeInternal {
|
||||
public:
|
||||
::google::protobuf::internal::ExplicitlyConstructed<Any>
|
||||
_instance;
|
||||
} _Any_default_instance_;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace protobuf_google_2fprotobuf_2fany_2eproto {
|
||||
void InitDefaultsAnyImpl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
|
||||
::google::protobuf::internal::InitProtobufDefaultsForceUnique();
|
||||
#else
|
||||
::google::protobuf::internal::InitProtobufDefaults();
|
||||
#endif // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
|
||||
{
|
||||
void* ptr = &::google::protobuf::_Any_default_instance_;
|
||||
new (ptr) ::google::protobuf::Any();
|
||||
::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
|
||||
}
|
||||
::google::protobuf::Any::InitAsDefaultInstance();
|
||||
}
|
||||
|
||||
void InitDefaultsAny() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &InitDefaultsAnyImpl);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata file_level_metadata[1];
|
||||
|
||||
const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
~0u, // no _has_bits_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Any, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Any, type_url_),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Any, value_),
|
||||
};
|
||||
static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ 0, -1, sizeof(::google::protobuf::Any)},
|
||||
};
|
||||
|
||||
static ::google::protobuf::Message const * const file_default_instances[] = {
|
||||
reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::_Any_default_instance_),
|
||||
};
|
||||
|
||||
void protobuf_AssignDescriptors() {
|
||||
AddDescriptors();
|
||||
::google::protobuf::MessageFactory* factory = NULL;
|
||||
AssignDescriptors(
|
||||
"google/protobuf/any.proto", schemas, file_default_instances, TableStruct::offsets, factory,
|
||||
file_level_metadata, NULL, NULL);
|
||||
}
|
||||
|
||||
void protobuf_AssignDescriptorsOnce() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
|
||||
}
|
||||
|
||||
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD;
|
||||
void protobuf_RegisterTypes(const ::std::string&) {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1);
|
||||
}
|
||||
|
||||
void AddDescriptorsImpl() {
|
||||
InitDefaults();
|
||||
static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
"\n\031google/protobuf/any.proto\022\017google.prot"
|
||||
"obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002"
|
||||
" \001(\014Bo\n\023com.google.protobufB\010AnyProtoP\001Z"
|
||||
"%github.com/golang/protobuf/ptypes/any\242\002"
|
||||
"\003GPB\252\002\036Google.Protobuf.WellKnownTypesb\006p"
|
||||
"roto3"
|
||||
};
|
||||
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
|
||||
descriptor, 205);
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
||||
"google/protobuf/any.proto", &protobuf_RegisterTypes);
|
||||
}
|
||||
|
||||
void AddDescriptors() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
|
||||
}
|
||||
// Force AddDescriptors() to be called at dynamic initialization time.
|
||||
struct StaticDescriptorInitializer {
|
||||
StaticDescriptorInitializer() {
|
||||
AddDescriptors();
|
||||
}
|
||||
} static_descriptor_initializer;
|
||||
} // namespace protobuf_google_2fprotobuf_2fany_2eproto
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
void Any::InitAsDefaultInstance() {
|
||||
}
|
||||
void Any::PackFrom(const ::google::protobuf::Message& message) {
|
||||
_any_metadata_.PackFrom(message);
|
||||
}
|
||||
|
||||
void Any::PackFrom(const ::google::protobuf::Message& message,
|
||||
const ::std::string& type_url_prefix) {
|
||||
_any_metadata_.PackFrom(message, type_url_prefix);
|
||||
}
|
||||
|
||||
bool Any::UnpackTo(::google::protobuf::Message* message) const {
|
||||
return _any_metadata_.UnpackTo(message);
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
const int Any::kTypeUrlFieldNumber;
|
||||
const int Any::kValueFieldNumber;
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
|
||||
Any::Any()
|
||||
: ::google::protobuf::Message(), _internal_metadata_(NULL), _any_metadata_(&type_url_, &value_) {
|
||||
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
|
||||
::protobuf_google_2fprotobuf_2fany_2eproto::InitDefaultsAny();
|
||||
}
|
||||
SharedCtor();
|
||||
// @@protoc_insertion_point(constructor:google.protobuf.Any)
|
||||
}
|
||||
Any::Any(const Any& from)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(NULL),
|
||||
_cached_size_(0),
|
||||
_any_metadata_(&type_url_, &value_) {
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
if (from.type_url().size() > 0) {
|
||||
type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_);
|
||||
}
|
||||
value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
if (from.value().size() > 0) {
|
||||
value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_);
|
||||
}
|
||||
// @@protoc_insertion_point(copy_constructor:google.protobuf.Any)
|
||||
}
|
||||
|
||||
void Any::SharedCtor() {
|
||||
type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
_cached_size_ = 0;
|
||||
}
|
||||
|
||||
Any::~Any() {
|
||||
// @@protoc_insertion_point(destructor:google.protobuf.Any)
|
||||
SharedDtor();
|
||||
}
|
||||
|
||||
void Any::SharedDtor() {
|
||||
type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
|
||||
void Any::SetCachedSize(int size) const {
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
}
|
||||
const ::google::protobuf::Descriptor* Any::descriptor() {
|
||||
::protobuf_google_2fprotobuf_2fany_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return ::protobuf_google_2fprotobuf_2fany_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
|
||||
}
|
||||
|
||||
const Any& Any::default_instance() {
|
||||
::protobuf_google_2fprotobuf_2fany_2eproto::InitDefaultsAny();
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
Any* Any::New(::google::protobuf::Arena* arena) const {
|
||||
Any* n = new Any;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void Any::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.Any)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
_internal_metadata_.Clear();
|
||||
}
|
||||
|
||||
bool Any::MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) {
|
||||
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
|
||||
::google::protobuf::uint32 tag;
|
||||
// @@protoc_insertion_point(parse_start:google.protobuf.Any)
|
||||
for (;;) {
|
||||
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
|
||||
tag = p.first;
|
||||
if (!p.second) goto handle_unusual;
|
||||
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
|
||||
// string type_url = 1;
|
||||
case 1: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
|
||||
input, this->mutable_type_url()));
|
||||
DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->type_url().data(), static_cast<int>(this->type_url().length()),
|
||||
::google::protobuf::internal::WireFormatLite::PARSE,
|
||||
"google.protobuf.Any.type_url"));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
case 2: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
|
||||
input, this->mutable_value()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
handle_unusual:
|
||||
if (tag == 0) {
|
||||
goto success;
|
||||
}
|
||||
DO_(::google::protobuf::internal::WireFormat::SkipField(
|
||||
input, tag, _internal_metadata_.mutable_unknown_fields()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success:
|
||||
// @@protoc_insertion_point(parse_success:google.protobuf.Any)
|
||||
return true;
|
||||
failure:
|
||||
// @@protoc_insertion_point(parse_failure:google.protobuf.Any)
|
||||
return false;
|
||||
#undef DO_
|
||||
}
|
||||
|
||||
void Any::SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const {
|
||||
// @@protoc_insertion_point(serialize_start:google.protobuf.Any)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// string type_url = 1;
|
||||
if (this->type_url().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->type_url().data(), static_cast<int>(this->type_url().length()),
|
||||
::google::protobuf::internal::WireFormatLite::SERIALIZE,
|
||||
"google.protobuf.Any.type_url");
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
|
||||
1, this->type_url(), output);
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
if (this->value().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
|
||||
2, this->value(), output);
|
||||
}
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_end:google.protobuf.Any)
|
||||
}
|
||||
|
||||
::google::protobuf::uint8* Any::InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const {
|
||||
(void)deterministic; // Unused
|
||||
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// string type_url = 1;
|
||||
if (this->type_url().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->type_url().data(), static_cast<int>(this->type_url().length()),
|
||||
::google::protobuf::internal::WireFormatLite::SERIALIZE,
|
||||
"google.protobuf.Any.type_url");
|
||||
target =
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
||||
1, this->type_url(), target);
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
if (this->value().size() > 0) {
|
||||
target =
|
||||
::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
|
||||
2, this->value(), target);
|
||||
}
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Any)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t Any::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any)
|
||||
size_t total_size = 0;
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
total_size +=
|
||||
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()));
|
||||
}
|
||||
// string type_url = 1;
|
||||
if (this->type_url().size() > 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::StringSize(
|
||||
this->type_url());
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
if (this->value().size() > 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::BytesSize(
|
||||
this->value());
|
||||
}
|
||||
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = cached_size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void Any::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Any)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
const Any* source =
|
||||
::google::protobuf::internal::DynamicCastToGenerated<const Any>(
|
||||
&from);
|
||||
if (source == NULL) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Any)
|
||||
::google::protobuf::internal::ReflectionOps::Merge(from, this);
|
||||
} else {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Any)
|
||||
MergeFrom(*source);
|
||||
}
|
||||
}
|
||||
|
||||
void Any::MergeFrom(const Any& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
if (from.type_url().size() > 0) {
|
||||
|
||||
type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_);
|
||||
}
|
||||
if (from.value().size() > 0) {
|
||||
|
||||
value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_);
|
||||
}
|
||||
}
|
||||
|
||||
void Any::CopyFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Any)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
void Any::CopyFrom(const Any& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Any)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool Any::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Any::Swap(Any* other) {
|
||||
if (other == this) return;
|
||||
InternalSwap(other);
|
||||
}
|
||||
void Any::InternalSwap(Any* other) {
|
||||
using std::swap;
|
||||
type_url_.Swap(&other->type_url_);
|
||||
value_.Swap(&other->value_);
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
swap(_cached_size_, other->_cached_size_);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata Any::GetMetadata() const {
|
||||
protobuf_google_2fprotobuf_2fany_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return ::protobuf_google_2fprotobuf_2fany_2eproto::file_level_metadata[kIndexInFileMessages];
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
-323
@@ -1,323 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/any.proto
|
||||
|
||||
#ifndef PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
|
||||
#define PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3005000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3005001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_table_driven.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
#include <google/protobuf/any.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace protobuf_google_2fprotobuf_2fany_2eproto {
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct LIBPROTOBUF_EXPORT TableStruct {
|
||||
static const ::google::protobuf::internal::ParseTableField entries[];
|
||||
static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
|
||||
static const ::google::protobuf::internal::ParseTable schema[1];
|
||||
static const ::google::protobuf::internal::FieldMetadata field_metadata[];
|
||||
static const ::google::protobuf::internal::SerializationTable serialization_table[];
|
||||
static const ::google::protobuf::uint32 offsets[];
|
||||
};
|
||||
void LIBPROTOBUF_EXPORT AddDescriptors();
|
||||
void LIBPROTOBUF_EXPORT InitDefaultsAnyImpl();
|
||||
void LIBPROTOBUF_EXPORT InitDefaultsAny();
|
||||
inline void LIBPROTOBUF_EXPORT InitDefaults() {
|
||||
InitDefaultsAny();
|
||||
}
|
||||
} // namespace protobuf_google_2fprotobuf_2fany_2eproto
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class Any;
|
||||
class AnyDefaultTypeInternal;
|
||||
LIBPROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ {
|
||||
public:
|
||||
Any();
|
||||
virtual ~Any();
|
||||
|
||||
Any(const Any& from);
|
||||
|
||||
inline Any& operator=(const Any& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
#if LANG_CXX11
|
||||
Any(Any&& from) noexcept
|
||||
: Any() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline Any& operator=(Any&& from) noexcept {
|
||||
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
|
||||
if (this != &from) InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const Any& default_instance();
|
||||
|
||||
static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
|
||||
static inline const Any* internal_default_instance() {
|
||||
return reinterpret_cast<const Any*>(
|
||||
&_Any_default_instance_);
|
||||
}
|
||||
static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
// implements Any -----------------------------------------------
|
||||
|
||||
void PackFrom(const ::google::protobuf::Message& message);
|
||||
void PackFrom(const ::google::protobuf::Message& message,
|
||||
const ::std::string& type_url_prefix);
|
||||
bool UnpackTo(::google::protobuf::Message* message) const;
|
||||
template<typename T> bool Is() const {
|
||||
return _any_metadata_.Is<T>();
|
||||
}
|
||||
|
||||
void Swap(Any* other);
|
||||
friend void swap(Any& a, Any& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline Any* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
|
||||
Any* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const Any& from);
|
||||
void MergeFrom(const Any& from);
|
||||
void Clear() PROTOBUF_FINAL;
|
||||
bool IsInitialized() const PROTOBUF_FINAL;
|
||||
|
||||
size_t ByteSizeLong() const PROTOBUF_FINAL;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
|
||||
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const PROTOBUF_FINAL;
|
||||
void InternalSwap(Any* other);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return NULL;
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return NULL;
|
||||
}
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// string type_url = 1;
|
||||
void clear_type_url();
|
||||
static const int kTypeUrlFieldNumber = 1;
|
||||
const ::std::string& type_url() const;
|
||||
void set_type_url(const ::std::string& value);
|
||||
#if LANG_CXX11
|
||||
void set_type_url(::std::string&& value);
|
||||
#endif
|
||||
void set_type_url(const char* value);
|
||||
void set_type_url(const char* value, size_t size);
|
||||
::std::string* mutable_type_url();
|
||||
::std::string* release_type_url();
|
||||
void set_allocated_type_url(::std::string* type_url);
|
||||
|
||||
// bytes value = 2;
|
||||
void clear_value();
|
||||
static const int kValueFieldNumber = 2;
|
||||
const ::std::string& value() const;
|
||||
void set_value(const ::std::string& value);
|
||||
#if LANG_CXX11
|
||||
void set_value(::std::string&& value);
|
||||
#endif
|
||||
void set_value(const char* value);
|
||||
void set_value(const void* value, size_t size);
|
||||
::std::string* mutable_value();
|
||||
::std::string* release_value();
|
||||
void set_allocated_value(::std::string* value);
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.Any)
|
||||
private:
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
::google::protobuf::internal::ArenaStringPtr type_url_;
|
||||
::google::protobuf::internal::ArenaStringPtr value_;
|
||||
mutable int _cached_size_;
|
||||
::google::protobuf::internal::AnyMetadata _any_metadata_;
|
||||
friend struct ::protobuf_google_2fprotobuf_2fany_2eproto::TableStruct;
|
||||
friend void ::protobuf_google_2fprotobuf_2fany_2eproto::InitDefaultsAnyImpl();
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// Any
|
||||
|
||||
// string type_url = 1;
|
||||
inline void Any::clear_type_url() {
|
||||
type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline const ::std::string& Any::type_url() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
|
||||
return type_url_.GetNoArena();
|
||||
}
|
||||
inline void Any::set_type_url(const ::std::string& value) {
|
||||
|
||||
type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
inline void Any::set_type_url(::std::string&& value) {
|
||||
|
||||
type_url_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.type_url)
|
||||
}
|
||||
#endif
|
||||
inline void Any::set_type_url(const char* value) {
|
||||
GOOGLE_DCHECK(value != NULL);
|
||||
|
||||
type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.Any.type_url)
|
||||
}
|
||||
inline void Any::set_type_url(const char* value, size_t size) {
|
||||
|
||||
type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url)
|
||||
}
|
||||
inline ::std::string* Any::mutable_type_url() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
|
||||
return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* Any::release_type_url() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.Any.type_url)
|
||||
|
||||
return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void Any::set_allocated_type_url(::std::string* type_url) {
|
||||
if (type_url != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url);
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
inline void Any::clear_value() {
|
||||
value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline const ::std::string& Any::value() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Any.value)
|
||||
return value_.GetNoArena();
|
||||
}
|
||||
inline void Any::set_value(const ::std::string& value) {
|
||||
|
||||
value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Any.value)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
inline void Any::set_value(::std::string&& value) {
|
||||
|
||||
value_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.value)
|
||||
}
|
||||
#endif
|
||||
inline void Any::set_value(const char* value) {
|
||||
GOOGLE_DCHECK(value != NULL);
|
||||
|
||||
value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.Any.value)
|
||||
}
|
||||
inline void Any::set_value(const void* value, size_t size) {
|
||||
|
||||
value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value)
|
||||
}
|
||||
inline ::std::string* Any::mutable_value() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
|
||||
return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* Any::release_value() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.Any.value)
|
||||
|
||||
return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void Any::set_allocated_value(::std::string* value) {
|
||||
if (value != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
|
||||
@@ -0,0 +1,99 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/any.h>
|
||||
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
std::string GetTypeUrl(StringPiece message_name,
|
||||
StringPiece type_url_prefix) {
|
||||
if (!type_url_prefix.empty() &&
|
||||
type_url_prefix[type_url_prefix.size() - 1] == '/') {
|
||||
return StrCat(type_url_prefix, message_name);
|
||||
} else {
|
||||
return StrCat(type_url_prefix, "/", message_name);
|
||||
}
|
||||
}
|
||||
|
||||
const char kAnyFullTypeName[] = "google.protobuf.Any";
|
||||
const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/";
|
||||
const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/";
|
||||
|
||||
bool AnyMetadata::InternalPackFrom(Arena* arena, const MessageLite& message,
|
||||
StringPiece type_url_prefix,
|
||||
StringPiece type_name) {
|
||||
type_url_->Set(&::google::protobuf::internal::GetEmptyString(),
|
||||
GetTypeUrl(type_name, type_url_prefix), arena);
|
||||
return message.SerializeToString(
|
||||
value_->Mutable(ArenaStringPtr::EmptyDefault{}, arena));
|
||||
}
|
||||
|
||||
bool AnyMetadata::InternalUnpackTo(StringPiece type_name,
|
||||
MessageLite* message) const {
|
||||
if (!InternalIs(type_name)) {
|
||||
return false;
|
||||
}
|
||||
return message->ParseFromString(value_->Get());
|
||||
}
|
||||
|
||||
bool AnyMetadata::InternalIs(StringPiece type_name) const {
|
||||
StringPiece type_url = type_url_->Get();
|
||||
return type_url.size() >= type_name.size() + 1 &&
|
||||
type_url[type_url.size() - type_name.size() - 1] == '/' &&
|
||||
HasSuffixString(type_url, type_name);
|
||||
}
|
||||
|
||||
bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
|
||||
std::string* full_type_name) {
|
||||
size_t pos = type_url.find_last_of('/');
|
||||
if (pos == std::string::npos || pos + 1 == type_url.size()) {
|
||||
return false;
|
||||
}
|
||||
if (url_prefix) {
|
||||
*url_prefix = std::string(type_url.substr(0, pos + 1));
|
||||
}
|
||||
*full_type_name = std::string(type_url.substr(pos + 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name) {
|
||||
return ParseAnyTypeUrl(type_url, nullptr, full_type_name);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
-1608
File diff suppressed because it is too large
Load Diff
-1165
File diff suppressed because it is too large
Load Diff
+407
-281
@@ -31,355 +31,481 @@
|
||||
#include <google/protobuf/arena.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <google/protobuf/arena_impl.h>
|
||||
|
||||
#include <google/protobuf/stubs/mutex.h>
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
static const size_t kMinCleanupListElements = 8;
|
||||
static const size_t kMaxCleanupListElements = 64; // 1kB on 64-bit.
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
static SerialArena::Memory AllocateMemory(const AllocationPolicy* policy_ptr,
|
||||
size_t last_size, size_t min_bytes) {
|
||||
AllocationPolicy policy; // default policy
|
||||
if (policy_ptr) policy = *policy_ptr;
|
||||
size_t size;
|
||||
if (last_size != 0) {
|
||||
// Double the current block size, up to a limit.
|
||||
auto max_size = policy.max_block_size;
|
||||
size = std::min(2 * last_size, max_size);
|
||||
} else {
|
||||
size = policy.start_block_size;
|
||||
}
|
||||
// Verify that min_bytes + kBlockHeaderSize won't overflow.
|
||||
GOOGLE_CHECK_LE(min_bytes,
|
||||
std::numeric_limits<size_t>::max() - SerialArena::kBlockHeaderSize);
|
||||
size = std::max(size, SerialArena::kBlockHeaderSize + min_bytes);
|
||||
|
||||
google::protobuf::internal::SequenceNumber ArenaImpl::lifecycle_id_generator_;
|
||||
void* mem;
|
||||
if (policy.block_alloc == nullptr) {
|
||||
mem = ::operator new(size);
|
||||
} else {
|
||||
mem = policy.block_alloc(size);
|
||||
}
|
||||
return {mem, size};
|
||||
}
|
||||
|
||||
class GetDeallocator {
|
||||
public:
|
||||
GetDeallocator(const AllocationPolicy* policy, size_t* space_allocated)
|
||||
: dealloc_(policy ? policy->block_dealloc : nullptr),
|
||||
space_allocated_(space_allocated) {}
|
||||
|
||||
void operator()(SerialArena::Memory mem) const {
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
// This memory was provided by the underlying allocator as unpoisoned,
|
||||
// so return it in an unpoisoned state.
|
||||
ASAN_UNPOISON_MEMORY_REGION(mem.ptr, mem.size);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
if (dealloc_) {
|
||||
dealloc_(mem.ptr, mem.size);
|
||||
} else {
|
||||
#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation)
|
||||
::operator delete(mem.ptr, mem.size);
|
||||
#else
|
||||
::operator delete(mem.ptr);
|
||||
#endif
|
||||
}
|
||||
*space_allocated_ += mem.size;
|
||||
}
|
||||
|
||||
private:
|
||||
void (*dealloc_)(void*, size_t);
|
||||
size_t* space_allocated_;
|
||||
};
|
||||
|
||||
SerialArena::SerialArena(Block* b, void* owner) : space_allocated_(b->size) {
|
||||
owner_ = owner;
|
||||
head_ = b;
|
||||
ptr_ = b->Pointer(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize);
|
||||
limit_ = b->Pointer(b->size & static_cast<size_t>(-8));
|
||||
}
|
||||
|
||||
SerialArena* SerialArena::New(Memory mem, void* owner) {
|
||||
GOOGLE_DCHECK_LE(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize, mem.size);
|
||||
|
||||
auto b = new (mem.ptr) Block{nullptr, mem.size};
|
||||
return new (b->Pointer(kBlockHeaderSize)) SerialArena(b, owner);
|
||||
}
|
||||
|
||||
template <typename Deallocator>
|
||||
SerialArena::Memory SerialArena::Free(Deallocator deallocator) {
|
||||
Block* b = head_;
|
||||
Memory mem = {b, b->size};
|
||||
while (b->next) {
|
||||
b = b->next; // We must first advance before deleting this block
|
||||
deallocator(mem);
|
||||
mem = {b, b->size};
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
PROTOBUF_NOINLINE
|
||||
std::pair<void*, SerialArena::CleanupNode*>
|
||||
SerialArena::AllocateAlignedWithCleanupFallback(
|
||||
size_t n, const AllocationPolicy* policy) {
|
||||
AllocateNewBlock(n + kCleanupSize, policy);
|
||||
return AllocateFromExistingWithCleanupFallback(n);
|
||||
}
|
||||
|
||||
PROTOBUF_NOINLINE
|
||||
void* SerialArena::AllocateAlignedFallback(size_t n,
|
||||
const AllocationPolicy* policy) {
|
||||
AllocateNewBlock(n, policy);
|
||||
return AllocateFromExisting(n);
|
||||
}
|
||||
|
||||
void SerialArena::AllocateNewBlock(size_t n, const AllocationPolicy* policy) {
|
||||
// Sync limit to block
|
||||
head_->start = reinterpret_cast<CleanupNode*>(limit_);
|
||||
|
||||
// Record how much used in this block.
|
||||
space_used_ += ptr_ - head_->Pointer(kBlockHeaderSize);
|
||||
|
||||
auto mem = AllocateMemory(policy, head_->size, n);
|
||||
// We don't want to emit an expensive RMW instruction that requires
|
||||
// exclusive access to a cacheline. Hence we write it in terms of a
|
||||
// regular add.
|
||||
auto relaxed = std::memory_order_relaxed;
|
||||
space_allocated_.store(space_allocated_.load(relaxed) + mem.size, relaxed);
|
||||
head_ = new (mem.ptr) Block{head_, mem.size};
|
||||
ptr_ = head_->Pointer(kBlockHeaderSize);
|
||||
limit_ = head_->Pointer(head_->size);
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_POISON_MEMORY_REGION(ptr_, limit_ - ptr_);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
}
|
||||
|
||||
uint64_t SerialArena::SpaceUsed() const {
|
||||
uint64_t space_used = ptr_ - head_->Pointer(kBlockHeaderSize);
|
||||
space_used += space_used_;
|
||||
// Remove the overhead of the SerialArena itself.
|
||||
space_used -= ThreadSafeArena::kSerialArenaSize;
|
||||
return space_used;
|
||||
}
|
||||
|
||||
void SerialArena::CleanupList() {
|
||||
Block* b = head_;
|
||||
b->start = reinterpret_cast<CleanupNode*>(limit_);
|
||||
do {
|
||||
auto* limit = reinterpret_cast<CleanupNode*>(
|
||||
b->Pointer(b->size & static_cast<size_t>(-8)));
|
||||
auto it = b->start;
|
||||
auto num = limit - it;
|
||||
if (num > 0) {
|
||||
for (; it < limit; it++) {
|
||||
it->cleanup(it->elem);
|
||||
}
|
||||
}
|
||||
b = b->next;
|
||||
} while (b);
|
||||
}
|
||||
|
||||
|
||||
ThreadSafeArena::CacheAlignedLifecycleIdGenerator
|
||||
ThreadSafeArena::lifecycle_id_generator_;
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
|
||||
ThreadSafeArena::ThreadCache& ThreadSafeArena::thread_cache() {
|
||||
static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
|
||||
new internal::ThreadLocalStorage<ThreadCache>();
|
||||
return *thread_cache_->Get();
|
||||
}
|
||||
#elif defined(PROTOBUF_USE_DLLS)
|
||||
ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
|
||||
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL };
|
||||
ThreadSafeArena::ThreadCache& ThreadSafeArena::thread_cache() {
|
||||
static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_ = {
|
||||
0, static_cast<LifecycleIdAtomic>(-1), nullptr};
|
||||
return thread_cache_;
|
||||
}
|
||||
#else
|
||||
GOOGLE_THREAD_LOCAL ArenaImpl::ThreadCache ArenaImpl::thread_cache_ = {-1, NULL};
|
||||
PROTOBUF_THREAD_LOCAL ThreadSafeArena::ThreadCache
|
||||
ThreadSafeArena::thread_cache_ = {0, static_cast<LifecycleIdAtomic>(-1),
|
||||
nullptr};
|
||||
#endif
|
||||
|
||||
void ArenaImpl::Init() {
|
||||
lifecycle_id_ = lifecycle_id_generator_.GetNext();
|
||||
google::protobuf::internal::NoBarrier_Store(&hint_, 0);
|
||||
google::protobuf::internal::NoBarrier_Store(&threads_, 0);
|
||||
|
||||
if (initial_block_) {
|
||||
// Thread which calls Init() owns the first block. This allows the
|
||||
// single-threaded case to allocate on the first block without having to
|
||||
// perform atomic operations.
|
||||
InitBlock(initial_block_, &thread_cache(), options_.initial_block_size);
|
||||
ThreadInfo* info = NewThreadInfo(initial_block_);
|
||||
info->next = NULL;
|
||||
google::protobuf::internal::NoBarrier_Store(&threads_,
|
||||
reinterpret_cast<google::protobuf::internal::AtomicWord>(info));
|
||||
google::protobuf::internal::NoBarrier_Store(&space_allocated_,
|
||||
options_.initial_block_size);
|
||||
CacheBlock(initial_block_);
|
||||
} else {
|
||||
google::protobuf::internal::NoBarrier_Store(&space_allocated_, 0);
|
||||
}
|
||||
}
|
||||
|
||||
ArenaImpl::~ArenaImpl() {
|
||||
// Have to do this in a first pass, because some of the destructors might
|
||||
// refer to memory in other blocks.
|
||||
CleanupList();
|
||||
FreeBlocks();
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::Reset() {
|
||||
// Have to do this in a first pass, because some of the destructors might
|
||||
// refer to memory in other blocks.
|
||||
CleanupList();
|
||||
uint64 space_allocated = FreeBlocks();
|
||||
void ThreadSafeArena::InitializeFrom(void* mem, size_t size) {
|
||||
GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(mem) & 7, 0u);
|
||||
GOOGLE_DCHECK(!AllocPolicy()); // Reset should call InitializeWithPolicy instead.
|
||||
Init();
|
||||
|
||||
return space_allocated;
|
||||
// Ignore initial block if it is too small.
|
||||
if (mem != nullptr && size >= kBlockHeaderSize + kSerialArenaSize) {
|
||||
alloc_policy_.set_is_user_owned_initial_block(true);
|
||||
SetInitialBlock(mem, size);
|
||||
}
|
||||
}
|
||||
|
||||
ArenaImpl::Block* ArenaImpl::NewBlock(void* me, Block* my_last_block,
|
||||
size_t min_bytes) {
|
||||
size_t size;
|
||||
if (my_last_block != NULL) {
|
||||
// Double the current block size, up to a limit.
|
||||
size = std::min(2 * my_last_block->size, options_.max_block_size);
|
||||
void ThreadSafeArena::InitializeWithPolicy(void* mem, size_t size,
|
||||
AllocationPolicy policy) {
|
||||
#ifndef NDEBUG
|
||||
const uint64_t old_alloc_policy = alloc_policy_.get_raw();
|
||||
// If there was a policy (e.g., in Reset()), make sure flags were preserved.
|
||||
#define GOOGLE_DCHECK_POLICY_FLAGS_() \
|
||||
if (old_alloc_policy > 3) \
|
||||
GOOGLE_CHECK_EQ(old_alloc_policy & 3, alloc_policy_.get_raw() & 3)
|
||||
#else
|
||||
#define GOOGLE_DCHECK_POLICY_FLAGS_()
|
||||
#endif // NDEBUG
|
||||
|
||||
if (policy.IsDefault()) {
|
||||
// Legacy code doesn't use the API above, but provides the initial block
|
||||
// through ArenaOptions. I suspect most do not touch the allocation
|
||||
// policy parameters.
|
||||
InitializeFrom(mem, size);
|
||||
GOOGLE_DCHECK_POLICY_FLAGS_();
|
||||
return;
|
||||
}
|
||||
GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(mem) & 7, 0u);
|
||||
Init();
|
||||
|
||||
// Ignore initial block if it is too small. We include an optional
|
||||
// AllocationPolicy in this check, so that this can be allocated on the
|
||||
// first block.
|
||||
constexpr size_t kAPSize = internal::AlignUpTo8(sizeof(AllocationPolicy));
|
||||
constexpr size_t kMinimumSize = kBlockHeaderSize + kSerialArenaSize + kAPSize;
|
||||
|
||||
// The value for alloc_policy_ stores whether or not allocations should be
|
||||
// recorded.
|
||||
alloc_policy_.set_should_record_allocs(
|
||||
policy.metrics_collector != nullptr &&
|
||||
policy.metrics_collector->RecordAllocs());
|
||||
// Make sure we have an initial block to store the AllocationPolicy.
|
||||
if (mem != nullptr && size >= kMinimumSize) {
|
||||
alloc_policy_.set_is_user_owned_initial_block(true);
|
||||
} else {
|
||||
size = options_.start_block_size;
|
||||
auto tmp = AllocateMemory(&policy, 0, kMinimumSize);
|
||||
mem = tmp.ptr;
|
||||
size = tmp.size;
|
||||
}
|
||||
// Verify that min_bytes + kHeaderSize won't overflow.
|
||||
GOOGLE_CHECK_LE(min_bytes, std::numeric_limits<size_t>::max() - kHeaderSize);
|
||||
size = std::max(size, kHeaderSize + min_bytes);
|
||||
SetInitialBlock(mem, size);
|
||||
|
||||
Block* b = reinterpret_cast<Block*>(options_.block_alloc(size));
|
||||
InitBlock(b, me, size);
|
||||
google::protobuf::internal::NoBarrier_AtomicIncrement(&space_allocated_, size);
|
||||
return b;
|
||||
}
|
||||
|
||||
void ArenaImpl::InitBlock(Block* b, void *me, size_t size) {
|
||||
b->pos = kHeaderSize;
|
||||
b->size = size;
|
||||
b->owner = me;
|
||||
b->next = NULL;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
// Poison the rest of the block for ASAN. It was unpoisoned by the underlying
|
||||
// malloc but it's not yet usable until we return it as part of an allocation.
|
||||
ASAN_POISON_MEMORY_REGION(
|
||||
reinterpret_cast<char*>(b) + b->pos, b->size - b->pos);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
}
|
||||
|
||||
ArenaImpl::CleanupChunk* ArenaImpl::ExpandCleanupList(CleanupChunk* cleanup,
|
||||
Block* b) {
|
||||
size_t size = cleanup ? cleanup->size * 2 : kMinCleanupListElements;
|
||||
size = std::min(size, kMaxCleanupListElements);
|
||||
size_t bytes = internal::AlignUpTo8(CleanupChunk::SizeOf(size));
|
||||
if (b->avail() < bytes) {
|
||||
b = GetBlock(bytes);
|
||||
auto sa = threads_.load(std::memory_order_relaxed);
|
||||
// We ensured enough space so this cannot fail.
|
||||
void* p;
|
||||
if (!sa || !sa->MaybeAllocateAligned(kAPSize, &p)) {
|
||||
GOOGLE_LOG(FATAL) << "MaybeAllocateAligned cannot fail here.";
|
||||
return;
|
||||
}
|
||||
CleanupChunk* list =
|
||||
reinterpret_cast<CleanupChunk*>(AllocFromBlock(b, bytes));
|
||||
list->next = b->thread_info->cleanup;
|
||||
list->size = size;
|
||||
list->len = 0;
|
||||
b->thread_info->cleanup = list;
|
||||
return list;
|
||||
new (p) AllocationPolicy{policy};
|
||||
// Low bits store flags, so they mustn't be overwritten.
|
||||
GOOGLE_DCHECK_EQ(0, reinterpret_cast<uintptr_t>(p) & 3);
|
||||
alloc_policy_.set_policy(reinterpret_cast<AllocationPolicy*>(p));
|
||||
GOOGLE_DCHECK_POLICY_FLAGS_();
|
||||
|
||||
#undef GOOGLE_DCHECK_POLICY_FLAGS_
|
||||
}
|
||||
|
||||
inline GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
void ArenaImpl::AddCleanupInBlock(
|
||||
Block* b, void* elem, void (*func)(void*)) {
|
||||
CleanupChunk* cleanup = b->thread_info->cleanup;
|
||||
if (cleanup == NULL || cleanup->len == cleanup->size) {
|
||||
cleanup = ExpandCleanupList(cleanup, b);
|
||||
void ThreadSafeArena::Init() {
|
||||
#ifndef NDEBUG
|
||||
const bool was_message_owned = IsMessageOwned();
|
||||
#endif // NDEBUG
|
||||
ThreadCache& tc = thread_cache();
|
||||
auto id = tc.next_lifecycle_id;
|
||||
// We increment lifecycle_id's by multiples of two so we can use bit 0 as
|
||||
// a tag.
|
||||
constexpr uint64_t kDelta = 2;
|
||||
constexpr uint64_t kInc = ThreadCache::kPerThreadIds * kDelta;
|
||||
if (PROTOBUF_PREDICT_FALSE((id & (kInc - 1)) == 0)) {
|
||||
constexpr auto relaxed = std::memory_order_relaxed;
|
||||
// On platforms that don't support uint64_t atomics we can certainly not
|
||||
// afford to increment by large intervals and expect uniqueness due to
|
||||
// wrapping, hence we only add by 1.
|
||||
id = lifecycle_id_generator_.id.fetch_add(1, relaxed) * kInc;
|
||||
}
|
||||
tc.next_lifecycle_id = id + kDelta;
|
||||
// Message ownership is stored in tag_and_id_, and is set in the constructor.
|
||||
// This flag bit must be preserved, even across calls to Reset().
|
||||
tag_and_id_ = id | (tag_and_id_ & kMessageOwnedArena);
|
||||
hint_.store(nullptr, std::memory_order_relaxed);
|
||||
threads_.store(nullptr, std::memory_order_relaxed);
|
||||
#ifndef NDEBUG
|
||||
GOOGLE_CHECK_EQ(was_message_owned, IsMessageOwned());
|
||||
#endif // NDEBUG
|
||||
}
|
||||
|
||||
void ThreadSafeArena::SetInitialBlock(void* mem, size_t size) {
|
||||
SerialArena* serial = SerialArena::New({mem, size}, &thread_cache());
|
||||
serial->set_next(NULL);
|
||||
threads_.store(serial, std::memory_order_relaxed);
|
||||
CacheSerialArena(serial);
|
||||
}
|
||||
|
||||
ThreadSafeArena::~ThreadSafeArena() {
|
||||
// Have to do this in a first pass, because some of the destructors might
|
||||
// refer to memory in other blocks.
|
||||
CleanupList();
|
||||
|
||||
size_t space_allocated = 0;
|
||||
auto mem = Free(&space_allocated);
|
||||
|
||||
// Policy is about to get deleted.
|
||||
auto* p = alloc_policy_.get();
|
||||
ArenaMetricsCollector* collector = p ? p->metrics_collector : nullptr;
|
||||
|
||||
if (alloc_policy_.is_user_owned_initial_block()) {
|
||||
space_allocated += mem.size;
|
||||
} else {
|
||||
GetDeallocator(alloc_policy_.get(), &space_allocated)(mem);
|
||||
}
|
||||
|
||||
CleanupNode* node = &cleanup->nodes[cleanup->len++];
|
||||
|
||||
node->elem = elem;
|
||||
node->cleanup = func;
|
||||
if (collector) collector->OnDestroy(space_allocated);
|
||||
}
|
||||
|
||||
void ArenaImpl::AddCleanup(void* elem, void (*cleanup)(void*)) {
|
||||
return AddCleanupInBlock(GetBlock(0), elem, cleanup);
|
||||
}
|
||||
|
||||
void* ArenaImpl::AllocateAligned(size_t n) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
|
||||
return AllocFromBlock(GetBlock(n), n);
|
||||
}
|
||||
|
||||
void* ArenaImpl::AllocateAlignedAndAddCleanup(size_t n,
|
||||
void (*cleanup)(void*)) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
|
||||
Block* b = GetBlock(n);
|
||||
void* mem = AllocFromBlock(b, n);
|
||||
AddCleanupInBlock(b, mem, cleanup);
|
||||
SerialArena::Memory ThreadSafeArena::Free(size_t* space_allocated) {
|
||||
SerialArena::Memory mem = {nullptr, 0};
|
||||
auto deallocator = GetDeallocator(alloc_policy_.get(), space_allocated);
|
||||
PerSerialArena([deallocator, &mem](SerialArena* a) {
|
||||
if (mem.ptr) deallocator(mem);
|
||||
mem = a->Free(deallocator);
|
||||
});
|
||||
return mem;
|
||||
}
|
||||
|
||||
inline GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
ArenaImpl::Block* ArenaImpl::GetBlock(size_t n) {
|
||||
Block* my_block = NULL;
|
||||
uint64_t ThreadSafeArena::Reset() {
|
||||
// Have to do this in a first pass, because some of the destructors might
|
||||
// refer to memory in other blocks.
|
||||
CleanupList();
|
||||
|
||||
// If this thread already owns a block in this arena then try to use that.
|
||||
// This fast path optimizes the case where multiple threads allocate from the
|
||||
// same arena.
|
||||
ThreadCache* tc = &thread_cache();
|
||||
if (tc->last_lifecycle_id_seen == lifecycle_id_) {
|
||||
my_block = tc->last_block_used_;
|
||||
if (my_block->avail() >= n) {
|
||||
return my_block;
|
||||
// Discard all blocks except the special block (if present).
|
||||
size_t space_allocated = 0;
|
||||
auto mem = Free(&space_allocated);
|
||||
|
||||
AllocationPolicy* policy = alloc_policy_.get();
|
||||
if (policy) {
|
||||
auto saved_policy = *policy;
|
||||
if (alloc_policy_.is_user_owned_initial_block()) {
|
||||
space_allocated += mem.size;
|
||||
} else {
|
||||
GetDeallocator(alloc_policy_.get(), &space_allocated)(mem);
|
||||
mem.ptr = nullptr;
|
||||
mem.size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether we own the last accessed block on this arena.
|
||||
// This fast path optimizes the case where a single thread uses multiple
|
||||
// arenas.
|
||||
Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&hint_));
|
||||
if (b != NULL && b->owner == tc) {
|
||||
my_block = b;
|
||||
if (my_block->avail() >= n) {
|
||||
return my_block;
|
||||
ArenaMetricsCollector* collector = saved_policy.metrics_collector;
|
||||
if (collector) collector->OnReset(space_allocated);
|
||||
InitializeWithPolicy(mem.ptr, mem.size, saved_policy);
|
||||
} else {
|
||||
GOOGLE_DCHECK(!alloc_policy_.should_record_allocs());
|
||||
// Nullptr policy
|
||||
if (alloc_policy_.is_user_owned_initial_block()) {
|
||||
space_allocated += mem.size;
|
||||
InitializeFrom(mem.ptr, mem.size);
|
||||
} else {
|
||||
GetDeallocator(alloc_policy_.get(), &space_allocated)(mem);
|
||||
Init();
|
||||
}
|
||||
}
|
||||
return GetBlockSlow(tc, my_block, n);
|
||||
}
|
||||
|
||||
inline GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
void* ArenaImpl::AllocFromBlock(Block* b, size_t n) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(b->pos), b->pos); // Must be already aligned.
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
GOOGLE_DCHECK_GE(b->avail(), n);
|
||||
size_t p = b->pos;
|
||||
b->pos = p + n;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(reinterpret_cast<char*>(b) + p, n);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
return reinterpret_cast<char*>(b) + p;
|
||||
}
|
||||
|
||||
ArenaImpl::Block* ArenaImpl::GetBlockSlow(void* me, Block* my_full_block,
|
||||
size_t n) {
|
||||
ThreadInfo* info =
|
||||
my_full_block ? my_full_block->thread_info : GetThreadInfo(me, n);
|
||||
GOOGLE_DCHECK(info != NULL);
|
||||
Block* b = info->head;
|
||||
if (b->avail() < n) {
|
||||
Block* new_b = NewBlock(me, b, n);
|
||||
new_b->thread_info = info;
|
||||
new_b->next = b;
|
||||
info->head = new_b;
|
||||
b = new_b;
|
||||
}
|
||||
CacheBlock(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::SpaceAllocated() const {
|
||||
return google::protobuf::internal::NoBarrier_Load(&space_allocated_);
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::SpaceUsed() const {
|
||||
ThreadInfo* info =
|
||||
reinterpret_cast<ThreadInfo*>(google::protobuf::internal::Acquire_Load(&threads_));
|
||||
uint64 space_used = 0;
|
||||
|
||||
for ( ; info; info = info->next) {
|
||||
// Remove the overhead of the ThreadInfo itself.
|
||||
space_used -= sizeof(ThreadInfo);
|
||||
for (Block* b = info->head; b; b = b->next) {
|
||||
space_used += (b->pos - kHeaderSize);
|
||||
}
|
||||
}
|
||||
|
||||
return space_used;
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::FreeBlocks() {
|
||||
uint64 space_allocated = 0;
|
||||
// By omitting an Acquire barrier we ensure that any user code that doesn't
|
||||
// properly synchronize Reset() or the destructor will throw a TSAN warning.
|
||||
ThreadInfo* info =
|
||||
reinterpret_cast<ThreadInfo*>(google::protobuf::internal::NoBarrier_Load(&threads_));
|
||||
|
||||
while (info) {
|
||||
// This is inside the block we are freeing, so we need to read it now.
|
||||
ThreadInfo* next_info = info->next;
|
||||
for (Block* b = info->head; b; ) {
|
||||
// This is inside the block we are freeing, so we need to read it now.
|
||||
Block* next_block = b->next;
|
||||
space_allocated += (b->size);
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
// This memory was provided by the underlying allocator as unpoisoned, so
|
||||
// return it in an unpoisoned state.
|
||||
ASAN_UNPOISON_MEMORY_REGION(reinterpret_cast<char*>(b), b->size);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
if (b != initial_block_) {
|
||||
options_.block_dealloc(b, b->size);
|
||||
}
|
||||
|
||||
b = next_block;
|
||||
}
|
||||
info = next_info;
|
||||
}
|
||||
|
||||
return space_allocated;
|
||||
}
|
||||
|
||||
void ArenaImpl::CleanupList() {
|
||||
// By omitting an Acquire barrier we ensure that any user code that doesn't
|
||||
// properly synchronize Reset() or the destructor will throw a TSAN warning.
|
||||
ThreadInfo* info =
|
||||
reinterpret_cast<ThreadInfo*>(google::protobuf::internal::NoBarrier_Load(&threads_));
|
||||
|
||||
for ( ; info; info = info->next) {
|
||||
CleanupChunk* list = info->cleanup;
|
||||
while (list) {
|
||||
size_t n = list->len;
|
||||
CleanupNode* node = &list->nodes[list->len - 1];
|
||||
for (size_t i = 0; i < n; i++, node--) {
|
||||
node->cleanup(node->elem);
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
std::pair<void*, SerialArena::CleanupNode*>
|
||||
ThreadSafeArena::AllocateAlignedWithCleanup(size_t n,
|
||||
const std::type_info* type) {
|
||||
SerialArena* arena;
|
||||
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
|
||||
GetSerialArenaFast(&arena))) {
|
||||
return arena->AllocateAlignedWithCleanup(n, alloc_policy_.get());
|
||||
} else {
|
||||
return AllocateAlignedWithCleanupFallback(n, type);
|
||||
}
|
||||
}
|
||||
|
||||
ArenaImpl::ThreadInfo* ArenaImpl::NewThreadInfo(Block* b) {
|
||||
GOOGLE_DCHECK(FindThreadInfo(b->owner) == NULL);
|
||||
ThreadInfo* info =
|
||||
reinterpret_cast<ThreadInfo*>(AllocFromBlock(b, sizeof(ThreadInfo)));
|
||||
b->thread_info = info;
|
||||
info->owner = b->owner;
|
||||
info->head = b;
|
||||
info->cleanup = NULL;
|
||||
return info;
|
||||
void ThreadSafeArena::AddCleanup(void* elem, void (*cleanup)(void*)) {
|
||||
SerialArena* arena;
|
||||
if (PROTOBUF_PREDICT_FALSE(!GetSerialArenaFast(&arena))) {
|
||||
arena = GetSerialArenaFallback(&thread_cache());
|
||||
}
|
||||
arena->AddCleanup(elem, cleanup, AllocPolicy());
|
||||
}
|
||||
|
||||
ArenaImpl::ThreadInfo* ArenaImpl::FindThreadInfo(void* me) {
|
||||
ThreadInfo* info =
|
||||
reinterpret_cast<ThreadInfo*>(google::protobuf::internal::Acquire_Load(&threads_));
|
||||
for ( ; info; info = info->next) {
|
||||
if (info->owner == me) {
|
||||
return info;
|
||||
PROTOBUF_NOINLINE
|
||||
void* ThreadSafeArena::AllocateAlignedFallback(size_t n,
|
||||
const std::type_info* type) {
|
||||
if (alloc_policy_.should_record_allocs()) {
|
||||
alloc_policy_.RecordAlloc(type, n);
|
||||
SerialArena* arena;
|
||||
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
return arena->AllocateAligned(n, alloc_policy_.get());
|
||||
}
|
||||
}
|
||||
return GetSerialArenaFallback(&thread_cache())
|
||||
->AllocateAligned(n, alloc_policy_.get());
|
||||
}
|
||||
|
||||
PROTOBUF_NOINLINE
|
||||
std::pair<void*, SerialArena::CleanupNode*>
|
||||
ThreadSafeArena::AllocateAlignedWithCleanupFallback(
|
||||
size_t n, const std::type_info* type) {
|
||||
if (alloc_policy_.should_record_allocs()) {
|
||||
alloc_policy_.RecordAlloc(type, n);
|
||||
SerialArena* arena;
|
||||
if (GetSerialArenaFast(&arena)) {
|
||||
return arena->AllocateAlignedWithCleanup(n, alloc_policy_.get());
|
||||
}
|
||||
}
|
||||
return GetSerialArenaFallback(&thread_cache())
|
||||
->AllocateAlignedWithCleanup(n, alloc_policy_.get());
|
||||
}
|
||||
|
||||
uint64_t ThreadSafeArena::SpaceAllocated() const {
|
||||
SerialArena* serial = threads_.load(std::memory_order_acquire);
|
||||
uint64_t res = 0;
|
||||
for (; serial; serial = serial->next()) {
|
||||
res += serial->SpaceAllocated();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
uint64_t ThreadSafeArena::SpaceUsed() const {
|
||||
SerialArena* serial = threads_.load(std::memory_order_acquire);
|
||||
uint64_t space_used = 0;
|
||||
for (; serial; serial = serial->next()) {
|
||||
space_used += serial->SpaceUsed();
|
||||
}
|
||||
return space_used - (alloc_policy_.get() ? sizeof(AllocationPolicy) : 0);
|
||||
}
|
||||
|
||||
void ThreadSafeArena::CleanupList() {
|
||||
PerSerialArena([](SerialArena* a) { a->CleanupList(); });
|
||||
}
|
||||
|
||||
PROTOBUF_NOINLINE
|
||||
SerialArena* ThreadSafeArena::GetSerialArenaFallback(void* me) {
|
||||
// Look for this SerialArena in our linked list.
|
||||
SerialArena* serial = threads_.load(std::memory_order_acquire);
|
||||
for (; serial; serial = serial->next()) {
|
||||
if (serial->owner() == me) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
if (!serial) {
|
||||
// This thread doesn't have any SerialArena, which also means it doesn't
|
||||
// have any blocks yet. So we'll allocate its first block now.
|
||||
serial = SerialArena::New(
|
||||
AllocateMemory(alloc_policy_.get(), 0, kSerialArenaSize), me);
|
||||
|
||||
ArenaImpl::ThreadInfo* ArenaImpl::GetThreadInfo(void* me, size_t n) {
|
||||
ThreadInfo* info = FindThreadInfo(me);
|
||||
|
||||
if (!info) {
|
||||
// This thread doesn't have any ThreadInfo, which also means it doesn't have
|
||||
// any blocks yet. So we'll allocate its first block now.
|
||||
Block* b = NewBlock(me, NULL, sizeof(ThreadInfo) + n);
|
||||
info = NewThreadInfo(b);
|
||||
|
||||
google::protobuf::internal::AtomicWord head;
|
||||
SerialArena* head = threads_.load(std::memory_order_relaxed);
|
||||
do {
|
||||
head = google::protobuf::internal::NoBarrier_Load(&threads_);
|
||||
info->next = reinterpret_cast<ThreadInfo*>(head);
|
||||
} while (google::protobuf::internal::Release_CompareAndSwap(
|
||||
&threads_, head, reinterpret_cast<google::protobuf::internal::AtomicWord>(info)) != head);
|
||||
serial->set_next(head);
|
||||
} while (!threads_.compare_exchange_weak(
|
||||
head, serial, std::memory_order_release, std::memory_order_relaxed));
|
||||
}
|
||||
|
||||
return info;
|
||||
CacheSerialArena(serial);
|
||||
return serial;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
void Arena::CallDestructorHooks() {
|
||||
uint64 space_allocated = impl_.SpaceAllocated();
|
||||
// Call the reset hook
|
||||
if (on_arena_reset_ != NULL) {
|
||||
on_arena_reset_(this, hooks_cookie_, space_allocated);
|
||||
}
|
||||
|
||||
// Call the destruction hook
|
||||
if (on_arena_destruction_ != NULL) {
|
||||
on_arena_destruction_(this, hooks_cookie_, space_allocated);
|
||||
}
|
||||
PROTOBUF_FUNC_ALIGN(32)
|
||||
void* Arena::AllocateAlignedNoHook(size_t n) {
|
||||
return impl_.AllocateAligned(n, nullptr);
|
||||
}
|
||||
|
||||
void Arena::OnArenaAllocation(const std::type_info* allocated_type,
|
||||
size_t n) const {
|
||||
if (on_arena_allocation_ != NULL) {
|
||||
on_arena_allocation_(allocated_type, n, hooks_cookie_);
|
||||
}
|
||||
PROTOBUF_FUNC_ALIGN(32)
|
||||
void* Arena::AllocateAlignedWithHook(size_t n, const std::type_info* type) {
|
||||
return impl_.AllocateAligned(n, type);
|
||||
}
|
||||
|
||||
PROTOBUF_FUNC_ALIGN(32)
|
||||
std::pair<void*, internal::SerialArena::CleanupNode*>
|
||||
Arena::AllocateAlignedWithCleanup(size_t n, const std::type_info* type) {
|
||||
return impl_.AllocateAlignedWithCleanup(n, type);
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
+474
-587
File diff suppressed because it is too large
Load Diff
+457
-137
@@ -33,85 +33,168 @@
|
||||
#ifndef GOOGLE_PROTOBUF_ARENA_IMPL_H__
|
||||
#define GOOGLE_PROTOBUF_ARENA_IMPL_H__
|
||||
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <google/protobuf/stubs/atomic_sequence_num.h>
|
||||
#include <google/protobuf/stubs/atomicops.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/mutex.h>
|
||||
#include <google/protobuf/stubs/type_traits.h>
|
||||
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
inline size_t AlignUpTo8(size_t n) {
|
||||
inline constexpr size_t AlignUpTo8(size_t n) {
|
||||
// Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.)
|
||||
return (n + 7) & -8;
|
||||
return (n + 7) & static_cast<size_t>(-8);
|
||||
}
|
||||
|
||||
// This class provides the core Arena memory allocation library. Different
|
||||
// implementations only need to implement the public interface below.
|
||||
// Arena is not a template type as that would only be useful if all protos
|
||||
// in turn would be templates, which will/cannot happen. However separating
|
||||
// the memory allocation part from the cruft of the API users expect we can
|
||||
// use #ifdef the select the best implementation based on hardware / OS.
|
||||
class LIBPROTOBUF_EXPORT ArenaImpl {
|
||||
using LifecycleIdAtomic = uint64_t;
|
||||
|
||||
// MetricsCollector collects stats for a particular arena.
|
||||
class PROTOBUF_EXPORT ArenaMetricsCollector {
|
||||
public:
|
||||
struct Options {
|
||||
size_t start_block_size;
|
||||
size_t max_block_size;
|
||||
char* initial_block;
|
||||
size_t initial_block_size;
|
||||
void* (*block_alloc)(size_t);
|
||||
void (*block_dealloc)(void*, size_t);
|
||||
ArenaMetricsCollector(bool record_allocs) : record_allocs_(record_allocs) {}
|
||||
|
||||
template <typename O>
|
||||
explicit Options(const O& options)
|
||||
: start_block_size(options.start_block_size),
|
||||
max_block_size(options.max_block_size),
|
||||
initial_block(options.initial_block),
|
||||
initial_block_size(options.initial_block_size),
|
||||
block_alloc(options.block_alloc),
|
||||
block_dealloc(options.block_dealloc) {}
|
||||
};
|
||||
// Invoked when the arena is about to be destroyed. This method will
|
||||
// typically finalize any metric collection and delete the collector.
|
||||
// space_allocated is the space used by the arena.
|
||||
virtual void OnDestroy(uint64_t space_allocated) = 0;
|
||||
|
||||
template <typename O>
|
||||
explicit ArenaImpl(const O& options) : options_(options) {
|
||||
if (options_.initial_block != NULL && options_.initial_block_size > 0) {
|
||||
GOOGLE_CHECK_GE(options_.initial_block_size, sizeof(Block))
|
||||
<< ": Initial block size too small for header.";
|
||||
initial_block_ = reinterpret_cast<Block*>(options_.initial_block);
|
||||
} else {
|
||||
initial_block_ = NULL;
|
||||
}
|
||||
// OnReset() is called when the associated arena is reset.
|
||||
// space_allocated is the space used by the arena just before the reset.
|
||||
virtual void OnReset(uint64_t space_allocated) = 0;
|
||||
|
||||
Init();
|
||||
// OnAlloc is called when an allocation happens.
|
||||
// type_info is promised to be static - its lifetime extends to
|
||||
// match program's lifetime (It is given by typeid operator).
|
||||
// Note: typeid(void) will be passed as allocated_type every time we
|
||||
// intentionally want to avoid monitoring an allocation. (i.e. internal
|
||||
// allocations for managing the arena)
|
||||
virtual void OnAlloc(const std::type_info* allocated_type,
|
||||
uint64_t alloc_size) = 0;
|
||||
|
||||
// Does OnAlloc() need to be called? If false, metric collection overhead
|
||||
// will be reduced since we will not do extra work per allocation.
|
||||
bool RecordAllocs() { return record_allocs_; }
|
||||
|
||||
protected:
|
||||
// This class is destructed by the call to OnDestroy().
|
||||
~ArenaMetricsCollector() = default;
|
||||
const bool record_allocs_;
|
||||
};
|
||||
|
||||
struct AllocationPolicy {
|
||||
static constexpr size_t kDefaultStartBlockSize = 256;
|
||||
static constexpr size_t kDefaultMaxBlockSize = 8192;
|
||||
|
||||
size_t start_block_size = kDefaultStartBlockSize;
|
||||
size_t max_block_size = kDefaultMaxBlockSize;
|
||||
void* (*block_alloc)(size_t) = nullptr;
|
||||
void (*block_dealloc)(void*, size_t) = nullptr;
|
||||
ArenaMetricsCollector* metrics_collector = nullptr;
|
||||
|
||||
bool IsDefault() const {
|
||||
return start_block_size == kDefaultMaxBlockSize &&
|
||||
max_block_size == kDefaultMaxBlockSize && block_alloc == nullptr &&
|
||||
block_dealloc == nullptr && metrics_collector == nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// Tagged pointer to an AllocationPolicy.
|
||||
class TaggedAllocationPolicyPtr {
|
||||
public:
|
||||
constexpr TaggedAllocationPolicyPtr() : policy_(0) {}
|
||||
|
||||
explicit TaggedAllocationPolicyPtr(AllocationPolicy* policy)
|
||||
: policy_(reinterpret_cast<uintptr_t>(policy)) {}
|
||||
|
||||
void set_policy(AllocationPolicy* policy) {
|
||||
auto bits = policy_ & kTagsMask;
|
||||
policy_ = reinterpret_cast<uintptr_t>(policy) | bits;
|
||||
}
|
||||
|
||||
// Destructor deletes all owned heap allocated objects, and destructs objects
|
||||
// that have non-trivial destructors, except for proto2 message objects whose
|
||||
// destructors can be skipped. Also, frees all blocks except the initial block
|
||||
// if it was passed in.
|
||||
~ArenaImpl();
|
||||
AllocationPolicy* get() {
|
||||
return reinterpret_cast<AllocationPolicy*>(policy_ & kPtrMask);
|
||||
}
|
||||
const AllocationPolicy* get() const {
|
||||
return reinterpret_cast<const AllocationPolicy*>(policy_ & kPtrMask);
|
||||
}
|
||||
|
||||
uint64 Reset();
|
||||
AllocationPolicy& operator*() { return *get(); }
|
||||
const AllocationPolicy& operator*() const { return *get(); }
|
||||
|
||||
uint64 SpaceAllocated() const;
|
||||
uint64 SpaceUsed() const;
|
||||
AllocationPolicy* operator->() { return get(); }
|
||||
const AllocationPolicy* operator->() const { return get(); }
|
||||
|
||||
void* AllocateAligned(size_t n);
|
||||
bool is_user_owned_initial_block() const {
|
||||
return static_cast<bool>(get_mask<kUserOwnedInitialBlock>());
|
||||
}
|
||||
void set_is_user_owned_initial_block(bool v) {
|
||||
set_mask<kUserOwnedInitialBlock>(v);
|
||||
}
|
||||
|
||||
void* AllocateAlignedAndAddCleanup(size_t n, void (*cleanup)(void*));
|
||||
bool should_record_allocs() const {
|
||||
return static_cast<bool>(get_mask<kRecordAllocs>());
|
||||
}
|
||||
void set_should_record_allocs(bool v) { set_mask<kRecordAllocs>(v); }
|
||||
|
||||
// Add object pointer and cleanup function pointer to the list.
|
||||
void AddCleanup(void* elem, void (*cleanup)(void*));
|
||||
uintptr_t get_raw() const { return policy_; }
|
||||
|
||||
inline void RecordAlloc(const std::type_info* allocated_type,
|
||||
size_t n) const {
|
||||
get()->metrics_collector->OnAlloc(allocated_type, n);
|
||||
}
|
||||
|
||||
private:
|
||||
enum : uintptr_t {
|
||||
kUserOwnedInitialBlock = 1,
|
||||
kRecordAllocs = 2,
|
||||
};
|
||||
|
||||
static constexpr uintptr_t kTagsMask = 7;
|
||||
static constexpr uintptr_t kPtrMask = ~kTagsMask;
|
||||
|
||||
template <uintptr_t kMask>
|
||||
uintptr_t get_mask() const {
|
||||
return policy_ & kMask;
|
||||
}
|
||||
template <uintptr_t kMask>
|
||||
void set_mask(bool v) {
|
||||
if (v) {
|
||||
policy_ |= kMask;
|
||||
} else {
|
||||
policy_ &= ~kMask;
|
||||
}
|
||||
}
|
||||
uintptr_t policy_;
|
||||
};
|
||||
|
||||
// A simple arena allocator. Calls to allocate functions must be properly
|
||||
// serialized by the caller, hence this class cannot be used as a general
|
||||
// purpose allocator in a multi-threaded program. It serves as a building block
|
||||
// for ThreadSafeArena, which provides a thread-safe arena allocator.
|
||||
//
|
||||
// This class manages
|
||||
// 1) Arena bump allocation + owning memory blocks.
|
||||
// 2) Maintaining a cleanup list.
|
||||
// It delagetes the actual memory allocation back to ThreadSafeArena, which
|
||||
// contains the information on block growth policy and backing memory allocation
|
||||
// used.
|
||||
class PROTOBUF_EXPORT SerialArena {
|
||||
public:
|
||||
struct Memory {
|
||||
void* ptr;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
// Node contains the ptr of the object to be cleaned up and the associated
|
||||
// cleanup function ptr.
|
||||
struct CleanupNode {
|
||||
@@ -119,124 +202,361 @@ class LIBPROTOBUF_EXPORT ArenaImpl {
|
||||
void (*cleanup)(void*); // Function pointer to the destructor or deleter.
|
||||
};
|
||||
|
||||
// Cleanup uses a chunked linked list, to reduce pointer chasing.
|
||||
struct CleanupChunk {
|
||||
static size_t SizeOf(size_t i) {
|
||||
return sizeof(CleanupChunk) + (sizeof(CleanupNode) * (i - 1));
|
||||
void CleanupList();
|
||||
uint64_t SpaceAllocated() const {
|
||||
return space_allocated_.load(std::memory_order_relaxed);
|
||||
}
|
||||
uint64_t SpaceUsed() const;
|
||||
|
||||
bool HasSpace(size_t n) { return n <= static_cast<size_t>(limit_ - ptr_); }
|
||||
|
||||
void* AllocateAligned(size_t n, const AllocationPolicy* policy) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
GOOGLE_DCHECK_GE(limit_, ptr_);
|
||||
if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) {
|
||||
return AllocateAlignedFallback(n, policy);
|
||||
}
|
||||
size_t len; // Number of elements currently present.
|
||||
size_t size; // Total elements in the list.
|
||||
CleanupChunk* next; // Next node in the list.
|
||||
CleanupNode nodes[1]; // True length is |size|.
|
||||
};
|
||||
return AllocateFromExisting(n);
|
||||
}
|
||||
|
||||
struct Block;
|
||||
private:
|
||||
void* AllocateFromExisting(size_t n) {
|
||||
void* ret = ptr_;
|
||||
ptr_ += n;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(ret, n);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Tracks per-thread info. ThreadInfos are kept in a linked list.
|
||||
struct ThreadInfo {
|
||||
void *owner; // &ThreadCache of this thread;
|
||||
Block* head; // Head of linked list of blocks.
|
||||
CleanupChunk* cleanup; // Head of cleanup list.
|
||||
ThreadInfo* next; // Next ThreadInfo in this linked list.
|
||||
};
|
||||
public:
|
||||
// Allocate space if the current region provides enough space.
|
||||
bool MaybeAllocateAligned(size_t n, void** out) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
GOOGLE_DCHECK_GE(limit_, ptr_);
|
||||
if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) return false;
|
||||
*out = AllocateFromExisting(n);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<void*, CleanupNode*> AllocateAlignedWithCleanup(
|
||||
size_t n, const AllocationPolicy* policy) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
if (PROTOBUF_PREDICT_FALSE(!HasSpace(n + kCleanupSize))) {
|
||||
return AllocateAlignedWithCleanupFallback(n, policy);
|
||||
}
|
||||
return AllocateFromExistingWithCleanupFallback(n);
|
||||
}
|
||||
|
||||
private:
|
||||
std::pair<void*, CleanupNode*> AllocateFromExistingWithCleanupFallback(
|
||||
size_t n) {
|
||||
void* ret = ptr_;
|
||||
ptr_ += n;
|
||||
limit_ -= kCleanupSize;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(ret, n);
|
||||
ASAN_UNPOISON_MEMORY_REGION(limit_, kCleanupSize);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
return CreatePair(ret, reinterpret_cast<CleanupNode*>(limit_));
|
||||
}
|
||||
|
||||
public:
|
||||
void AddCleanup(void* elem, void (*cleanup)(void*),
|
||||
const AllocationPolicy* policy) {
|
||||
auto res = AllocateAlignedWithCleanup(0, policy);
|
||||
res.second->elem = elem;
|
||||
res.second->cleanup = cleanup;
|
||||
}
|
||||
|
||||
void* owner() const { return owner_; }
|
||||
SerialArena* next() const { return next_; }
|
||||
void set_next(SerialArena* next) { next_ = next; }
|
||||
|
||||
private:
|
||||
friend class ThreadSafeArena;
|
||||
friend class ArenaBenchmark;
|
||||
|
||||
// Creates a new SerialArena inside mem using the remaining memory as for
|
||||
// future allocations.
|
||||
static SerialArena* New(SerialArena::Memory mem, void* owner);
|
||||
// Free SerialArena returning the memory passed in to New
|
||||
template <typename Deallocator>
|
||||
Memory Free(Deallocator deallocator);
|
||||
|
||||
// Blocks are variable length malloc-ed objects. The following structure
|
||||
// describes the common header for all blocks.
|
||||
struct Block {
|
||||
void* owner; // &ThreadCache of thread that owns this block.
|
||||
ThreadInfo* thread_info; // ThreadInfo of thread that owns this block.
|
||||
Block* next; // Next block in arena (may have different owner)
|
||||
// ((char*) &block) + pos is next available byte. It is always
|
||||
// aligned at a multiple of 8 bytes.
|
||||
size_t pos;
|
||||
size_t size; // total size of the block.
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
size_t avail() const { return size - pos; }
|
||||
Block(Block* next, size_t size) : next(next), size(size), start(nullptr) {}
|
||||
|
||||
char* Pointer(size_t n) {
|
||||
GOOGLE_DCHECK(n <= size);
|
||||
return reinterpret_cast<char*>(this) + n;
|
||||
}
|
||||
|
||||
Block* const next;
|
||||
const size_t size;
|
||||
CleanupNode* start;
|
||||
// data follows
|
||||
};
|
||||
|
||||
struct ThreadCache {
|
||||
void* owner_; // &ThreadCache of this thread;
|
||||
Block* head_; // Head of linked list of blocks.
|
||||
SerialArena* next_; // Next SerialArena in this linked list.
|
||||
size_t space_used_ = 0; // Necessary for metrics.
|
||||
std::atomic<size_t> space_allocated_;
|
||||
|
||||
// Next pointer to allocate from. Always 8-byte aligned. Points inside
|
||||
// head_ (and head_->pos will always be non-canonical). We keep these
|
||||
// here to reduce indirection.
|
||||
char* ptr_;
|
||||
char* limit_;
|
||||
|
||||
// Constructor is private as only New() should be used.
|
||||
inline SerialArena(Block* b, void* owner);
|
||||
void* AllocateAlignedFallback(size_t n, const AllocationPolicy* policy);
|
||||
std::pair<void*, CleanupNode*> AllocateAlignedWithCleanupFallback(
|
||||
size_t n, const AllocationPolicy* policy);
|
||||
void AllocateNewBlock(size_t n, const AllocationPolicy* policy);
|
||||
|
||||
std::pair<void*, CleanupNode*> CreatePair(void* ptr, CleanupNode* node) {
|
||||
return {ptr, node};
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr size_t kBlockHeaderSize = AlignUpTo8(sizeof(Block));
|
||||
static constexpr size_t kCleanupSize = AlignUpTo8(sizeof(CleanupNode));
|
||||
};
|
||||
|
||||
// Tag type used to invoke the constructor of message-owned arena.
|
||||
// Only message-owned arenas use this constructor for creation.
|
||||
// Such constructors are internal implementation details of the library.
|
||||
struct MessageOwned {
|
||||
explicit MessageOwned() = default;
|
||||
};
|
||||
|
||||
// This class provides the core Arena memory allocation library. Different
|
||||
// implementations only need to implement the public interface below.
|
||||
// Arena is not a template type as that would only be useful if all protos
|
||||
// in turn would be templates, which will/cannot happen. However separating
|
||||
// the memory allocation part from the cruft of the API users expect we can
|
||||
// use #ifdef the select the best implementation based on hardware / OS.
|
||||
class PROTOBUF_EXPORT ThreadSafeArena {
|
||||
public:
|
||||
ThreadSafeArena() { Init(); }
|
||||
|
||||
// Constructor solely used by message-owned arena.
|
||||
ThreadSafeArena(internal::MessageOwned) : tag_and_id_(kMessageOwnedArena) {
|
||||
Init();
|
||||
}
|
||||
|
||||
ThreadSafeArena(char* mem, size_t size) { InitializeFrom(mem, size); }
|
||||
|
||||
explicit ThreadSafeArena(void* mem, size_t size,
|
||||
const AllocationPolicy& policy) {
|
||||
InitializeWithPolicy(mem, size, policy);
|
||||
}
|
||||
|
||||
// Destructor deletes all owned heap allocated objects, and destructs objects
|
||||
// that have non-trivial destructors, except for proto2 message objects whose
|
||||
// destructors can be skipped. Also, frees all blocks except the initial block
|
||||
// if it was passed in.
|
||||
~ThreadSafeArena();
|
||||
|
||||
uint64_t Reset();
|
||||
|
||||
uint64_t SpaceAllocated() const;
|
||||
uint64_t SpaceUsed() const;
|
||||
|
||||
void* AllocateAligned(size_t n, const std::type_info* type) {
|
||||
SerialArena* arena;
|
||||
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
|
||||
GetSerialArenaFast(&arena))) {
|
||||
return arena->AllocateAligned(n, AllocPolicy());
|
||||
} else {
|
||||
return AllocateAlignedFallback(n, type);
|
||||
}
|
||||
}
|
||||
|
||||
// This function allocates n bytes if the common happy case is true and
|
||||
// returns true. Otherwise does nothing and returns false. This strange
|
||||
// semantics is necessary to allow callers to program functions that only
|
||||
// have fallback function calls in tail position. This substantially improves
|
||||
// code for the happy path.
|
||||
PROTOBUF_NDEBUG_INLINE bool MaybeAllocateAligned(size_t n, void** out) {
|
||||
SerialArena* a;
|
||||
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
|
||||
GetSerialArenaFromThreadCache(&a))) {
|
||||
return a->MaybeAllocateAligned(n, out);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::pair<void*, SerialArena::CleanupNode*> AllocateAlignedWithCleanup(
|
||||
size_t n, const std::type_info* type);
|
||||
|
||||
// Add object pointer and cleanup function pointer to the list.
|
||||
void AddCleanup(void* elem, void (*cleanup)(void*));
|
||||
|
||||
// Checks whether this arena is message-owned.
|
||||
PROTOBUF_ALWAYS_INLINE bool IsMessageOwned() const {
|
||||
return tag_and_id_ & kMessageOwnedArena;
|
||||
}
|
||||
|
||||
private:
|
||||
// Unique for each arena. Changes on Reset().
|
||||
uint64_t tag_and_id_ = 0;
|
||||
// The LSB of tag_and_id_ indicates if the arena is message-owned.
|
||||
enum : uint64_t { kMessageOwnedArena = 1 };
|
||||
|
||||
TaggedAllocationPolicyPtr alloc_policy_; // Tagged pointer to AllocPolicy.
|
||||
|
||||
// Pointer to a linked list of SerialArena.
|
||||
std::atomic<SerialArena*> threads_;
|
||||
std::atomic<SerialArena*> hint_; // Fast thread-local block access
|
||||
|
||||
const AllocationPolicy* AllocPolicy() const { return alloc_policy_.get(); }
|
||||
void InitializeFrom(void* mem, size_t size);
|
||||
void InitializeWithPolicy(void* mem, size_t size, AllocationPolicy policy);
|
||||
void* AllocateAlignedFallback(size_t n, const std::type_info* type);
|
||||
std::pair<void*, SerialArena::CleanupNode*>
|
||||
AllocateAlignedWithCleanupFallback(size_t n, const std::type_info* type);
|
||||
|
||||
void Init();
|
||||
void SetInitialBlock(void* mem, size_t size);
|
||||
|
||||
// Delete or Destruct all objects owned by the arena.
|
||||
void CleanupList();
|
||||
|
||||
inline uint64_t LifeCycleId() const {
|
||||
return tag_and_id_ & ~kMessageOwnedArena;
|
||||
}
|
||||
|
||||
inline void CacheSerialArena(SerialArena* serial) {
|
||||
thread_cache().last_serial_arena = serial;
|
||||
thread_cache().last_lifecycle_id_seen = tag_and_id_;
|
||||
// TODO(haberman): evaluate whether we would gain efficiency by getting rid
|
||||
// of hint_. It's the only write we do to ThreadSafeArena in the allocation
|
||||
// path, which will dirty the cache line.
|
||||
|
||||
hint_.store(serial, std::memory_order_release);
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFast(SerialArena** arena) {
|
||||
if (GetSerialArenaFromThreadCache(arena)) return true;
|
||||
|
||||
// Check whether we own the last accessed SerialArena on this arena. This
|
||||
// fast path optimizes the case where a single thread uses multiple arenas.
|
||||
ThreadCache* tc = &thread_cache();
|
||||
SerialArena* serial = hint_.load(std::memory_order_acquire);
|
||||
if (PROTOBUF_PREDICT_TRUE(serial != NULL && serial->owner() == tc)) {
|
||||
*arena = serial;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFromThreadCache(
|
||||
SerialArena** arena) {
|
||||
// If this thread already owns a block in this arena then try to use that.
|
||||
// This fast path optimizes the case where multiple threads allocate from
|
||||
// the same arena.
|
||||
ThreadCache* tc = &thread_cache();
|
||||
if (PROTOBUF_PREDICT_TRUE(tc->last_lifecycle_id_seen == tag_and_id_)) {
|
||||
*arena = tc->last_serial_arena;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
SerialArena* GetSerialArenaFallback(void* me);
|
||||
|
||||
template <typename Functor>
|
||||
void PerSerialArena(Functor fn) {
|
||||
// By omitting an Acquire barrier we ensure that any user code that doesn't
|
||||
// properly synchronize Reset() or the destructor will throw a TSAN warning.
|
||||
SerialArena* serial = threads_.load(std::memory_order_relaxed);
|
||||
|
||||
for (; serial; serial = serial->next()) fn(serial);
|
||||
}
|
||||
|
||||
// Releases all memory except the first block which it returns. The first
|
||||
// block might be owned by the user and thus need some extra checks before
|
||||
// deleting.
|
||||
SerialArena::Memory Free(size_t* space_allocated);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4324)
|
||||
#endif
|
||||
struct alignas(64) ThreadCache {
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
// If we are using the ThreadLocalStorage class to store the ThreadCache,
|
||||
// then the ThreadCache's default constructor has to be responsible for
|
||||
// initializing it.
|
||||
ThreadCache() : last_lifecycle_id_seen(-1), last_block_used_(NULL) {}
|
||||
ThreadCache()
|
||||
: next_lifecycle_id(0),
|
||||
last_lifecycle_id_seen(-1),
|
||||
last_serial_arena(NULL) {}
|
||||
#endif
|
||||
|
||||
// Number of per-thread lifecycle IDs to reserve. Must be power of two.
|
||||
// To reduce contention on a global atomic, each thread reserves a batch of
|
||||
// IDs. The following number is calculated based on a stress test with
|
||||
// ~6500 threads all frequently allocating a new arena.
|
||||
static constexpr size_t kPerThreadIds = 256;
|
||||
// Next lifecycle ID available to this thread. We need to reserve a new
|
||||
// batch, if `next_lifecycle_id & (kPerThreadIds - 1) == 0`.
|
||||
uint64_t next_lifecycle_id;
|
||||
// The ThreadCache is considered valid as long as this matches the
|
||||
// lifecycle_id of the arena being used.
|
||||
int64 last_lifecycle_id_seen;
|
||||
Block* last_block_used_;
|
||||
uint64_t last_lifecycle_id_seen;
|
||||
SerialArena* last_serial_arena;
|
||||
};
|
||||
static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
|
||||
|
||||
// Lifecycle_id can be highly contended variable in a situation of lots of
|
||||
// arena creation. Make sure that other global variables are not sharing the
|
||||
// cacheline.
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4324)
|
||||
#endif
|
||||
struct alignas(64) CacheAlignedLifecycleIdGenerator {
|
||||
std::atomic<LifecycleIdAtomic> id;
|
||||
};
|
||||
static CacheAlignedLifecycleIdGenerator lifecycle_id_generator_;
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
// Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
|
||||
// local storage class we implemented.
|
||||
// iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
|
||||
// iOS does not support __thread keyword so we use a custom thread local
|
||||
// storage class we implemented.
|
||||
static ThreadCache& thread_cache();
|
||||
#elif defined(PROTOBUF_USE_DLLS)
|
||||
// Thread local variables cannot be exposed through DLL interface but we can
|
||||
// wrap them in static functions.
|
||||
static ThreadCache& thread_cache();
|
||||
#else
|
||||
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
|
||||
static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_;
|
||||
static ThreadCache& thread_cache() { return thread_cache_; }
|
||||
#endif
|
||||
|
||||
void Init();
|
||||
|
||||
// Free all blocks and return the total space used which is the sums of sizes
|
||||
// of the all the allocated blocks.
|
||||
uint64 FreeBlocks();
|
||||
|
||||
void AddCleanupInBlock(Block* b, void* elem, void (*func)(void*));
|
||||
CleanupChunk* ExpandCleanupList(CleanupChunk* cleanup, Block* b);
|
||||
// Delete or Destruct all objects owned by the arena.
|
||||
void CleanupList();
|
||||
|
||||
inline void CacheBlock(Block* block) {
|
||||
thread_cache().last_block_used_ = block;
|
||||
thread_cache().last_lifecycle_id_seen = lifecycle_id_;
|
||||
// TODO(haberman): evaluate whether we would gain efficiency by getting rid
|
||||
// of hint_. It's the only write we do to ArenaImpl in the allocation path,
|
||||
// which will dirty the cache line.
|
||||
google::protobuf::internal::Release_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(block));
|
||||
}
|
||||
|
||||
google::protobuf::internal::AtomicWord threads_; // Pointer to a linked list of ThreadInfo.
|
||||
google::protobuf::internal::AtomicWord hint_; // Fast thread-local block access
|
||||
google::protobuf::internal::AtomicWord space_allocated_; // Sum of sizes of all allocated blocks.
|
||||
|
||||
Block *initial_block_; // If non-NULL, points to the block that came from
|
||||
// user data.
|
||||
|
||||
// Returns a block owned by this thread.
|
||||
Block* GetBlock(size_t n);
|
||||
Block* GetBlockSlow(void* me, Block* my_full_block, size_t n);
|
||||
Block* NewBlock(void* me, Block* my_last_block, size_t min_bytes);
|
||||
void InitBlock(Block* b, void *me, size_t size);
|
||||
static void* AllocFromBlock(Block* b, size_t n);
|
||||
ThreadInfo* NewThreadInfo(Block* b);
|
||||
ThreadInfo* FindThreadInfo(void* me);
|
||||
ThreadInfo* GetThreadInfo(void* me, size_t n);
|
||||
|
||||
int64 lifecycle_id_; // Unique for each arena. Changes on Reset().
|
||||
|
||||
Options options_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArenaImpl);
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadSafeArena);
|
||||
// All protos have pointers back to the arena hence Arena must have
|
||||
// pointer stability.
|
||||
ThreadSafeArena(ThreadSafeArena&&) = delete;
|
||||
ThreadSafeArena& operator=(ThreadSafeArena&&) = delete;
|
||||
|
||||
public:
|
||||
// kHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8 to
|
||||
// protect the invariant that pos is always at a multiple of 8.
|
||||
static const size_t kHeaderSize = (sizeof(Block) + 7) & -8;
|
||||
#if LANG_CXX11
|
||||
static_assert(kHeaderSize % 8 == 0, "kHeaderSize must be a multiple of 8.");
|
||||
#endif
|
||||
// kBlockHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8
|
||||
// to protect the invariant that pos is always at a multiple of 8.
|
||||
static constexpr size_t kBlockHeaderSize = SerialArena::kBlockHeaderSize;
|
||||
static constexpr size_t kSerialArenaSize =
|
||||
(sizeof(SerialArena) + 7) & static_cast<size_t>(-8);
|
||||
static_assert(kBlockHeaderSize % 8 == 0,
|
||||
"kBlockHeaderSize must be a multiple of 8.");
|
||||
static_assert(kSerialArenaSize % 8 == 0,
|
||||
"kSerialArenaSize must be a multiple of 8.");
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ARENA_IMPL_H__
|
||||
|
||||
+246
-3
@@ -28,16 +28,259 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// The ArenaString implementation is not included in the open-source release. Do
|
||||
// not include this file in the distribution.
|
||||
|
||||
#include <google/protobuf/arenastring.h>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/stubs/mutex.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
// clang-format off
|
||||
#include <google/protobuf/port_def.inc>
|
||||
// clang-format on
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
const std::string& LazyString::Init() const {
|
||||
static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED};
|
||||
mu.Lock();
|
||||
const std::string* res = inited_.load(std::memory_order_acquire);
|
||||
if (res == nullptr) {
|
||||
auto init_value = init_value_;
|
||||
res = ::new (static_cast<void*>(string_buf_))
|
||||
std::string(init_value.ptr, init_value.size);
|
||||
inited_.store(res, std::memory_order_release);
|
||||
}
|
||||
mu.Unlock();
|
||||
return *res;
|
||||
}
|
||||
|
||||
|
||||
std::string* ArenaStringPtr::SetAndReturnNewString() {
|
||||
std::string* new_string = new std::string();
|
||||
tagged_ptr_.Set(new_string);
|
||||
return new_string;
|
||||
}
|
||||
|
||||
void ArenaStringPtr::DestroyNoArenaSlowPath() { delete UnsafeMutablePointer(); }
|
||||
|
||||
void ArenaStringPtr::Set(const std::string* default_value,
|
||||
ConstStringParam value, ::google::protobuf::Arena* arena) {
|
||||
if (IsDefault(default_value)) {
|
||||
tagged_ptr_.Set(Arena::Create<std::string>(arena, value));
|
||||
} else {
|
||||
UnsafeMutablePointer()->assign(value.data(), value.length());
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Set(const std::string* default_value, std::string&& value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (IsDefault(default_value)) {
|
||||
if (arena == nullptr) {
|
||||
tagged_ptr_.Set(new std::string(std::move(value)));
|
||||
} else {
|
||||
tagged_ptr_.Set(Arena::Create<std::string>(arena, std::move(value)));
|
||||
}
|
||||
} else if (IsDonatedString()) {
|
||||
std::string* current = tagged_ptr_.Get();
|
||||
auto* s = new (current) std::string(std::move(value));
|
||||
arena->OwnDestructor(s);
|
||||
tagged_ptr_.Set(s);
|
||||
} else /* !IsDonatedString() */ {
|
||||
*UnsafeMutablePointer() = std::move(value);
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Set(EmptyDefault, ConstStringParam value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
Set(&GetEmptyStringAlreadyInited(), value, arena);
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Set(EmptyDefault, std::string&& value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
Set(&GetEmptyStringAlreadyInited(), std::move(value), arena);
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Set(NonEmptyDefault, ConstStringParam value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
Set(nullptr, value, arena);
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Set(NonEmptyDefault, std::string&& value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
Set(nullptr, std::move(value), arena);
|
||||
}
|
||||
|
||||
std::string* ArenaStringPtr::Mutable(EmptyDefault, ::google::protobuf::Arena* arena) {
|
||||
if (!IsDonatedString() && !IsDefault(&GetEmptyStringAlreadyInited())) {
|
||||
return UnsafeMutablePointer();
|
||||
} else {
|
||||
return MutableSlow(arena);
|
||||
}
|
||||
}
|
||||
|
||||
std::string* ArenaStringPtr::Mutable(const LazyString& default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (!IsDonatedString() && !IsDefault(nullptr)) {
|
||||
return UnsafeMutablePointer();
|
||||
} else {
|
||||
return MutableSlow(arena, default_value);
|
||||
}
|
||||
}
|
||||
|
||||
std::string* ArenaStringPtr::MutableNoCopy(const std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (!IsDonatedString() && !IsDefault(default_value)) {
|
||||
return UnsafeMutablePointer();
|
||||
} else {
|
||||
GOOGLE_DCHECK(IsDefault(default_value));
|
||||
// Allocate empty. The contents are not relevant.
|
||||
std::string* new_string = Arena::Create<std::string>(arena);
|
||||
tagged_ptr_.Set(new_string);
|
||||
return new_string;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Lazy>
|
||||
std::string* ArenaStringPtr::MutableSlow(::google::protobuf::Arena* arena,
|
||||
const Lazy&... lazy_default) {
|
||||
const std::string* const default_value =
|
||||
sizeof...(Lazy) == 0 ? &GetEmptyStringAlreadyInited() : nullptr;
|
||||
GOOGLE_DCHECK(IsDefault(default_value));
|
||||
std::string* new_string =
|
||||
Arena::Create<std::string>(arena, lazy_default.get()...);
|
||||
tagged_ptr_.Set(new_string);
|
||||
return new_string;
|
||||
}
|
||||
|
||||
std::string* ArenaStringPtr::Release(const std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (IsDefault(default_value)) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return ReleaseNonDefault(default_value, arena);
|
||||
}
|
||||
}
|
||||
|
||||
std::string* ArenaStringPtr::ReleaseNonDefault(const std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
GOOGLE_DCHECK(!IsDefault(default_value));
|
||||
|
||||
if (!IsDonatedString()) {
|
||||
std::string* released;
|
||||
if (arena != nullptr) {
|
||||
released = new std::string;
|
||||
released->swap(*UnsafeMutablePointer());
|
||||
} else {
|
||||
released = UnsafeMutablePointer();
|
||||
}
|
||||
tagged_ptr_.Set(const_cast<std::string*>(default_value));
|
||||
return released;
|
||||
} else /* IsDonatedString() */ {
|
||||
GOOGLE_DCHECK(arena != nullptr);
|
||||
std::string* released = new std::string(Get());
|
||||
tagged_ptr_.Set(const_cast<std::string*>(default_value));
|
||||
return released;
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaStringPtr::SetAllocated(const std::string* default_value,
|
||||
std::string* value, ::google::protobuf::Arena* arena) {
|
||||
// Release what we have first.
|
||||
if (arena == nullptr && !IsDefault(default_value)) {
|
||||
delete UnsafeMutablePointer();
|
||||
}
|
||||
if (value == nullptr) {
|
||||
tagged_ptr_.Set(const_cast<std::string*>(default_value));
|
||||
} else {
|
||||
#ifdef NDEBUG
|
||||
tagged_ptr_.Set(value);
|
||||
if (arena != nullptr) {
|
||||
arena->Own(value);
|
||||
}
|
||||
#else
|
||||
// On debug builds, copy the string so the address differs. delete will
|
||||
// fail if value was a stack-allocated temporary/etc., which would have
|
||||
// failed when arena ran its cleanup list.
|
||||
std::string* new_value = Arena::Create<std::string>(arena, *value);
|
||||
delete value;
|
||||
tagged_ptr_.Set(new_value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Destroy(const std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (arena == nullptr) {
|
||||
GOOGLE_DCHECK(!IsDonatedString());
|
||||
if (!IsDefault(default_value)) {
|
||||
delete UnsafeMutablePointer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Destroy(EmptyDefault, ::google::protobuf::Arena* arena) {
|
||||
Destroy(&GetEmptyStringAlreadyInited(), arena);
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Destroy(NonEmptyDefault, ::google::protobuf::Arena* arena) {
|
||||
Destroy(nullptr, arena);
|
||||
}
|
||||
|
||||
void ArenaStringPtr::ClearToEmpty() {
|
||||
if (IsDefault(&GetEmptyStringAlreadyInited())) {
|
||||
// Already set to default -- do nothing.
|
||||
} else {
|
||||
// Unconditionally mask away the tag.
|
||||
//
|
||||
// UpdateDonatedString uses assign when capacity is larger than the new
|
||||
// value, which is trivially true in the donated string case.
|
||||
// const_cast<std::string*>(PtrValue<std::string>())->clear();
|
||||
tagged_ptr_.Get()->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaStringPtr::ClearToDefault(const LazyString& default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
(void)arena;
|
||||
if (IsDefault(nullptr)) {
|
||||
// Already set to default -- do nothing.
|
||||
} else if (!IsDonatedString()) {
|
||||
UnsafeMutablePointer()->assign(default_value.get());
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetStrWithHeapBuffer(std::string* str, ArenaStringPtr* s) {
|
||||
TaggedPtr<std::string> res;
|
||||
res.Set(str);
|
||||
s->UnsafeSetTaggedPointer(res);
|
||||
}
|
||||
|
||||
const char* EpsCopyInputStream::ReadArenaString(const char* ptr,
|
||||
ArenaStringPtr* s,
|
||||
Arena* arena) {
|
||||
GOOGLE_DCHECK(arena != nullptr);
|
||||
|
||||
int size = ReadSize(&ptr);
|
||||
if (!ptr) return nullptr;
|
||||
|
||||
auto* str = Arena::Create<std::string>(arena);
|
||||
ptr = ReadString(ptr, size, str);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
|
||||
SetStrWithHeapBuffer(str, s);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
+339
-257
@@ -32,307 +32,389 @@
|
||||
#define GOOGLE_PROTOBUF_ARENASTRING_H__
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/fastmem.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/port.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
// This is the implementation of arena string fields written for the open-source
|
||||
// release. The ArenaStringPtr struct below is an internal implementation class
|
||||
// and *should not be used* by user code. It is used to collect string
|
||||
// operations together into one place and abstract away the underlying
|
||||
// string-field pointer representation, so that (for example) an alternate
|
||||
// implementation that knew more about ::std::string's internals could integrate more
|
||||
// closely with the arena allocator.
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
struct LIBPROTOBUF_EXPORT ArenaStringPtr {
|
||||
inline void Set(const ::std::string* default_value,
|
||||
const ::std::string& value, ::google::protobuf::Arena* arena) {
|
||||
if (ptr_ == default_value) {
|
||||
CreateInstance(arena, &value);
|
||||
} else {
|
||||
*ptr_ = value;
|
||||
}
|
||||
template <typename T>
|
||||
class ExplicitlyConstructed;
|
||||
|
||||
class SwapFieldHelper;
|
||||
|
||||
// Lazy string instance to support string fields with non-empty default.
|
||||
// These are initialized on the first call to .get().
|
||||
class PROTOBUF_EXPORT LazyString {
|
||||
public:
|
||||
// We explicitly make LazyString an aggregate so that MSVC can do constant
|
||||
// initialization on it without marking it `constexpr`.
|
||||
// We do not want to use `constexpr` because it makes it harder to have extern
|
||||
// storage for it and causes library bloat.
|
||||
struct InitValue {
|
||||
const char* ptr;
|
||||
size_t size;
|
||||
};
|
||||
// We keep a union of the initialization value and the std::string to save on
|
||||
// space. We don't need the string array after Init() is done.
|
||||
union {
|
||||
mutable InitValue init_value_;
|
||||
alignas(std::string) mutable char string_buf_[sizeof(std::string)];
|
||||
};
|
||||
mutable std::atomic<const std::string*> inited_;
|
||||
|
||||
const std::string& get() const {
|
||||
// This check generates less code than a call-once invocation.
|
||||
auto* res = inited_.load(std::memory_order_acquire);
|
||||
if (PROTOBUF_PREDICT_FALSE(res == nullptr)) return Init();
|
||||
return *res;
|
||||
}
|
||||
|
||||
inline void SetLite(const ::std::string* default_value,
|
||||
const ::std::string& value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
Set(default_value, value, arena);
|
||||
private:
|
||||
// Initialize the string in `string_buf_`, update `inited_` and return it.
|
||||
// We return it here to avoid having to read it again in the inlined code.
|
||||
const std::string& Init() const;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TaggedPtr {
|
||||
public:
|
||||
TaggedPtr() = default;
|
||||
explicit constexpr TaggedPtr(const ExplicitlyConstructed<std::string>* ptr)
|
||||
: ptr_(const_cast<ExplicitlyConstructed<std::string>*>(ptr)) {}
|
||||
|
||||
void SetTagged(T* p) {
|
||||
Set(p);
|
||||
ptr_ = reinterpret_cast<void*>(as_int() | 1);
|
||||
}
|
||||
void Set(T* p) { ptr_ = p; }
|
||||
T* Get() const { return reinterpret_cast<T*>(as_int() & -2); }
|
||||
bool IsTagged() const { return as_int() & 1; }
|
||||
|
||||
// Returned value is only safe to dereference if IsTagged() == false.
|
||||
// It is safe to compare.
|
||||
T* UnsafeGet() const { return static_cast<T*>(ptr_); }
|
||||
|
||||
bool IsNull() { return ptr_ == nullptr; }
|
||||
|
||||
private:
|
||||
uintptr_t as_int() const { return reinterpret_cast<uintptr_t>(ptr_); }
|
||||
void* ptr_;
|
||||
};
|
||||
|
||||
static_assert(std::is_trivial<TaggedPtr<std::string>>::value,
|
||||
"TaggedPtr must be trivial");
|
||||
|
||||
// This class encapsulates a pointer to a std::string with or without a donated
|
||||
// buffer, tagged by bottom bit. It is a high-level wrapper that almost directly
|
||||
// corresponds to the interface required by string fields in generated
|
||||
// code. It replaces the old std::string* pointer in such cases.
|
||||
//
|
||||
// The object has different but similar code paths for when the default value is
|
||||
// the empty string and when it is a non-empty string.
|
||||
// The empty string is handled different throughout the library and there is a
|
||||
// single global instance of it we can share.
|
||||
//
|
||||
// For fields with an empty string default value, there are three distinct
|
||||
// states:
|
||||
//
|
||||
// - Pointer set to 'String' tag (LSB is 0), equal to
|
||||
// &GetEmptyStringAlreadyInited(): field is set to its default value. Points
|
||||
// to a true std::string*, but we do not own that std::string* (it's a
|
||||
// globally shared instance).
|
||||
//
|
||||
// - Pointer set to 'String' tag (LSB is 0), but not equal to the global empty
|
||||
// string: field points to a true std::string* instance that we own. This
|
||||
// instance is either on the heap or on the arena (i.e. registered on
|
||||
// free()/destructor-call list) as appropriate.
|
||||
//
|
||||
// - Pointer set to 'DonatedString' tag (LSB is 1): points to a std::string
|
||||
// instance with a buffer on the arena (arena is never nullptr in this case).
|
||||
//
|
||||
// For fields with a non-empty string default value, there are three distinct
|
||||
// states:
|
||||
//
|
||||
// - Pointer set to 'String' tag (LSB is 0), equal to `nullptr`:
|
||||
// Field is in "default" mode and does not point to any actual instance.
|
||||
// Methods that might need to create an instance of the object will pass a
|
||||
// `const LazyString&` for it.
|
||||
//
|
||||
// - Pointer set to 'String' tag (LSB is 0), but not equal to `nullptr`:
|
||||
// field points to a true std::string* instance that we own. This instance is
|
||||
// either on the heap or on the arena (i.e. registered on
|
||||
// free()/destructor-call list) as appropriate.
|
||||
//
|
||||
// - Pointer set to 'DonatedString' tag (LSB is 1): points to a std::string
|
||||
// instance with a buffer on the arena (arena is never nullptr in this case).
|
||||
//
|
||||
// Generated code and reflection code both ensure that ptr_ is never null for
|
||||
// fields with an empty default.
|
||||
// Because ArenaStringPtr is used in oneof unions, its constructor is a NOP and
|
||||
// so the field is always manually initialized via method calls.
|
||||
//
|
||||
// Side-note: why pass information about the default on every API call? Because
|
||||
// we don't want to hold it in a member variable, or else this would go into
|
||||
// every proto message instance. This would be a huge waste of space, since the
|
||||
// default instance pointer is typically a global (static class field). We want
|
||||
// the generated code to be as efficient as possible, and if we take
|
||||
// the default value information as a parameter that's in practice taken from a
|
||||
// static class field, and compare ptr_ to the default value, we end up with a
|
||||
// single "cmp %reg, GLOBAL" in the resulting machine code. (Note that this also
|
||||
// requires the String tag to be 0 so we can avoid the mask before comparing.)
|
||||
struct PROTOBUF_EXPORT ArenaStringPtr {
|
||||
ArenaStringPtr() = default;
|
||||
explicit constexpr ArenaStringPtr(
|
||||
const ExplicitlyConstructed<std::string>* default_value)
|
||||
: tagged_ptr_(default_value) {}
|
||||
|
||||
// Some methods below are overloaded on a `default_value` and on tags.
|
||||
// The tagged overloads help reduce code size in the callers in generated
|
||||
// code, while the `default_value` overloads are useful from reflection.
|
||||
// By-value empty struct arguments are elided in the ABI.
|
||||
struct EmptyDefault {};
|
||||
struct NonEmptyDefault {};
|
||||
|
||||
void Set(const std::string* default_value, ConstStringParam value,
|
||||
::google::protobuf::Arena* arena);
|
||||
void Set(const std::string* default_value, std::string&& value,
|
||||
::google::protobuf::Arena* arena);
|
||||
void Set(EmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena);
|
||||
void Set(EmptyDefault, std::string&& value, ::google::protobuf::Arena* arena);
|
||||
void Set(NonEmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena);
|
||||
void Set(NonEmptyDefault, std::string&& value, ::google::protobuf::Arena* arena);
|
||||
template <typename FirstParam>
|
||||
void Set(FirstParam p1, const char* str, ::google::protobuf::Arena* arena) {
|
||||
Set(p1, ConstStringParam(str), arena);
|
||||
}
|
||||
template <typename FirstParam>
|
||||
void Set(FirstParam p1, const char* str, size_t size,
|
||||
::google::protobuf::Arena* arena) {
|
||||
ConstStringParam sp{str, size}; // for string_view and `const string &`
|
||||
Set(p1, sp, arena);
|
||||
}
|
||||
template <typename FirstParam, typename RefWrappedType>
|
||||
void Set(FirstParam p1,
|
||||
std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena) {
|
||||
Set(p1, const_string_ref.get(), arena);
|
||||
}
|
||||
|
||||
template <typename FirstParam, typename SecondParam>
|
||||
void SetBytes(FirstParam p1, SecondParam&& p2, ::google::protobuf::Arena* arena) {
|
||||
Set(p1, static_cast<SecondParam&&>(p2), arena);
|
||||
}
|
||||
template <typename FirstParam>
|
||||
void SetBytes(FirstParam p1, const void* str, size_t size,
|
||||
::google::protobuf::Arena* arena) {
|
||||
// must work whether ConstStringParam is string_view or `const string &`
|
||||
ConstStringParam sp{static_cast<const char*>(str), size};
|
||||
Set(p1, sp, arena);
|
||||
}
|
||||
|
||||
// Basic accessors.
|
||||
inline const ::std::string& Get() const { return *ptr_; }
|
||||
|
||||
inline ::std::string* Mutable(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (ptr_ == default_value) {
|
||||
CreateInstance(arena, default_value);
|
||||
}
|
||||
return ptr_;
|
||||
PROTOBUF_NDEBUG_INLINE const std::string& Get() const {
|
||||
// Unconditionally mask away the tag.
|
||||
return *tagged_ptr_.Get();
|
||||
}
|
||||
PROTOBUF_NDEBUG_INLINE const std::string* GetPointer() const {
|
||||
// Unconditionally mask away the tag.
|
||||
return tagged_ptr_.Get();
|
||||
}
|
||||
|
||||
// Release returns a ::std::string* instance that is heap-allocated and is not
|
||||
// Own()'d by any arena. If the field was not set, it returns NULL. The caller
|
||||
// retains ownership. Clears this field back to NULL state. Used to implement
|
||||
// release_<field>() methods on generated classes.
|
||||
inline ::std::string* Release(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (ptr_ == default_value) {
|
||||
return NULL;
|
||||
}
|
||||
::std::string* released = NULL;
|
||||
if (arena != NULL) {
|
||||
// ptr_ is owned by the arena.
|
||||
released = new ::std::string;
|
||||
released->swap(*ptr_);
|
||||
} else {
|
||||
released = ptr_;
|
||||
}
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
return released;
|
||||
}
|
||||
// For fields with an empty default value.
|
||||
std::string* Mutable(EmptyDefault, ::google::protobuf::Arena* arena);
|
||||
// For fields with a non-empty default value.
|
||||
std::string* Mutable(const LazyString& default_value, ::google::protobuf::Arena* arena);
|
||||
|
||||
// UnsafeArenaRelease returns a ::std::string*, but it may be arena-owned (i.e.
|
||||
// have its destructor already registered) if arena != NULL. If the field was
|
||||
// not set, this returns NULL. This method clears this field back to NULL
|
||||
// state. Used to implement unsafe_arena_release_<field>() methods on
|
||||
// generated classes.
|
||||
inline ::std::string* UnsafeArenaRelease(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* /* arena */) {
|
||||
if (ptr_ == default_value) {
|
||||
return NULL;
|
||||
}
|
||||
::std::string* released = ptr_;
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
return released;
|
||||
}
|
||||
// Release returns a std::string* instance that is heap-allocated and is not
|
||||
// Own()'d by any arena. If the field is not set, this returns nullptr. The
|
||||
// caller retains ownership. Clears this field back to nullptr state. Used to
|
||||
// implement release_<field>() methods on generated classes.
|
||||
PROTOBUF_NODISCARD std::string* Release(const std::string* default_value,
|
||||
::google::protobuf::Arena* arena);
|
||||
PROTOBUF_NODISCARD std::string* ReleaseNonDefault(
|
||||
const std::string* default_value, ::google::protobuf::Arena* arena);
|
||||
|
||||
// Takes a string that is heap-allocated, and takes ownership. The string's
|
||||
// destructor is registered with the arena. Used to implement
|
||||
// Takes a std::string that is heap-allocated, and takes ownership. The
|
||||
// std::string's destructor is registered with the arena. Used to implement
|
||||
// set_allocated_<field> in generated classes.
|
||||
inline void SetAllocated(const ::std::string* default_value,
|
||||
::std::string* value, ::google::protobuf::Arena* arena) {
|
||||
if (arena == NULL && ptr_ != default_value) {
|
||||
Destroy(default_value, arena);
|
||||
}
|
||||
if (value != NULL) {
|
||||
ptr_ = value;
|
||||
if (arena != NULL) {
|
||||
arena->Own(value);
|
||||
}
|
||||
} else {
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
// Takes a string that has lifetime equal to the arena's lifetime. The arena
|
||||
// must be non-null. It is safe only to pass this method a value returned by
|
||||
// UnsafeArenaRelease() on another field of a message in the same arena. Used
|
||||
// to implement unsafe_arena_set_allocated_<field> in generated classes.
|
||||
inline void UnsafeArenaSetAllocated(const ::std::string* default_value,
|
||||
::std::string* value,
|
||||
::google::protobuf::Arena* /* arena */) {
|
||||
if (value != NULL) {
|
||||
ptr_ = value;
|
||||
} else {
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
}
|
||||
}
|
||||
void SetAllocated(const std::string* default_value, std::string* value,
|
||||
::google::protobuf::Arena* arena);
|
||||
|
||||
// Swaps internal pointers. Arena-safety semantics: this is guarded by the
|
||||
// logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
|
||||
// 'unsafe' if called directly.
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) {
|
||||
std::swap(ptr_, other->ptr_);
|
||||
}
|
||||
inline PROTOBUF_NDEBUG_INLINE static void InternalSwap(
|
||||
const std::string* default_value, ArenaStringPtr* rhs, Arena* rhs_arena,
|
||||
ArenaStringPtr* lhs, Arena* lhs_arena);
|
||||
|
||||
// Frees storage (if not on an arena).
|
||||
inline void Destroy(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (arena == NULL && ptr_ != default_value) {
|
||||
delete ptr_;
|
||||
}
|
||||
}
|
||||
void Destroy(const std::string* default_value, ::google::protobuf::Arena* arena);
|
||||
void Destroy(EmptyDefault, ::google::protobuf::Arena* arena);
|
||||
void Destroy(NonEmptyDefault, ::google::protobuf::Arena* arena);
|
||||
|
||||
// Clears content, but keeps allocated string if arena != NULL, to avoid the
|
||||
// overhead of heap operations. After this returns, the content (as seen by
|
||||
// the user) will always be the empty string. Assumes that |default_value|
|
||||
// is an empty string.
|
||||
inline void ClearToEmpty(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* /* arena */) {
|
||||
if (ptr_ == default_value) {
|
||||
// Already set to default (which is empty) -- do nothing.
|
||||
} else {
|
||||
ptr_->clear();
|
||||
}
|
||||
}
|
||||
// Clears content, but keeps allocated std::string, to avoid the overhead of
|
||||
// heap operations. After this returns, the content (as seen by the user) will
|
||||
// always be the empty std::string. Assumes that |default_value| is an empty
|
||||
// std::string.
|
||||
void ClearToEmpty();
|
||||
|
||||
// Clears content, but keeps allocated string if arena != NULL, to avoid the
|
||||
// overhead of heap operations. After this returns, the content (as seen by
|
||||
// the user) will always be equal to |default_value|.
|
||||
inline void ClearToDefault(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* /* arena */) {
|
||||
if (ptr_ == default_value) {
|
||||
// Already set to default -- do nothing.
|
||||
} else {
|
||||
// Have another allocated string -- rather than throwing this away and
|
||||
// resetting ptr_ to the canonical default string instance, we just reuse
|
||||
// this instance.
|
||||
*ptr_ = *default_value;
|
||||
}
|
||||
}
|
||||
// Clears content, assuming that the current value is not the empty
|
||||
// string default.
|
||||
void ClearNonDefaultToEmpty();
|
||||
|
||||
// Clears content, but keeps allocated std::string if arena != nullptr, to
|
||||
// avoid the overhead of heap operations. After this returns, the content
|
||||
// (as seen by the user) will always be equal to |default_value|.
|
||||
void ClearToDefault(const LazyString& default_value, ::google::protobuf::Arena* arena);
|
||||
|
||||
// Called from generated code / reflection runtime only. Resets value to point
|
||||
// to a default string pointer, with the semantics that this ArenaStringPtr
|
||||
// does not own the pointed-to memory. Disregards initial value of ptr_ (so
|
||||
// this is the *ONLY* safe method to call after construction or when
|
||||
// reinitializing after becoming the active field in a oneof union).
|
||||
inline void UnsafeSetDefault(const ::std::string* default_value) {
|
||||
// Casting away 'const' is safe here: accessors ensure that ptr_ is only
|
||||
// returned as a const if it is equal to default_value.
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
// to a default string pointer, with the semantics that this
|
||||
// ArenaStringPtr does not own the pointed-to memory. Disregards initial value
|
||||
// of ptr_ (so this is the *ONLY* safe method to call after construction or
|
||||
// when reinitializing after becoming the active field in a oneof union).
|
||||
inline void UnsafeSetDefault(const std::string* default_value);
|
||||
|
||||
// Returns a mutable pointer, but doesn't initialize the string to the
|
||||
// default value.
|
||||
std::string* MutableNoArenaNoDefault(const std::string* default_value);
|
||||
|
||||
// Get a mutable pointer with unspecified contents.
|
||||
// Similar to `MutableNoArenaNoDefault`, but also handles the arena case.
|
||||
// If the value was donated, the contents are discarded.
|
||||
std::string* MutableNoCopy(const std::string* default_value,
|
||||
::google::protobuf::Arena* arena);
|
||||
|
||||
// Destroy the string. Assumes `arena == nullptr`.
|
||||
void DestroyNoArena(const std::string* default_value);
|
||||
|
||||
// Internal setter used only at parse time to directly set a donated string
|
||||
// value.
|
||||
void UnsafeSetTaggedPointer(TaggedPtr<std::string> value) {
|
||||
tagged_ptr_ = value;
|
||||
}
|
||||
// Generated code only! An optimization, in certain cases the generated
|
||||
// code is certain we can obtain a std::string with no default checks and
|
||||
// tag tests.
|
||||
std::string* UnsafeMutablePointer() PROTOBUF_RETURNS_NONNULL;
|
||||
|
||||
// The 'NoArena' variants of methods below assume arena == NULL and are
|
||||
// optimized to provide very little overhead relative to a raw string pointer
|
||||
// (while still being in-memory compatible with other code that assumes
|
||||
// ArenaStringPtr). Note the invariant that a class instance that has only
|
||||
// ever been mutated by NoArena methods must *only* be in the String state
|
||||
// (i.e., tag bits are not used), *NEVER* ArenaString. This allows all
|
||||
// tagged-pointer manipulations to be avoided.
|
||||
inline void SetNoArena(const ::std::string* default_value,
|
||||
const ::std::string& value) {
|
||||
if (ptr_ == default_value) {
|
||||
CreateInstanceNoArena(&value);
|
||||
} else {
|
||||
*ptr_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
#if LANG_CXX11
|
||||
void SetNoArena(const ::std::string* default_value, ::std::string&& value) {
|
||||
if (IsDefault(default_value)) {
|
||||
ptr_ = new ::std::string(std::move(value));
|
||||
} else {
|
||||
*ptr_ = std::move(value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void AssignWithDefault(const ::std::string* default_value, ArenaStringPtr value);
|
||||
|
||||
inline const ::std::string& GetNoArena() const { return *ptr_; }
|
||||
|
||||
inline ::std::string* MutableNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ == default_value) {
|
||||
CreateInstanceNoArena(default_value);
|
||||
}
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
inline ::std::string* ReleaseNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ == default_value) {
|
||||
return NULL;
|
||||
} else {
|
||||
::std::string* released = ptr_;
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
return released;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetAllocatedNoArena(const ::std::string* default_value,
|
||||
::std::string* value) {
|
||||
if (ptr_ != default_value) {
|
||||
delete ptr_;
|
||||
}
|
||||
if (value != NULL) {
|
||||
ptr_ = value;
|
||||
} else {
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
inline void DestroyNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ != default_value) {
|
||||
delete ptr_;
|
||||
}
|
||||
}
|
||||
|
||||
inline void ClearToEmptyNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ == default_value) {
|
||||
// Nothing: already equal to default (which is the empty string).
|
||||
} else {
|
||||
ptr_->clear();
|
||||
}
|
||||
}
|
||||
|
||||
inline void ClearToDefaultNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ == default_value) {
|
||||
// Nothing: already set to default.
|
||||
} else {
|
||||
// Reuse existing allocated instance.
|
||||
*ptr_ = *default_value;
|
||||
}
|
||||
}
|
||||
|
||||
// Internal accessor used only at parse time to provide direct access to the
|
||||
// raw pointer from the shared parse routine (in the non-arenas case). The
|
||||
// parse routine does the string allocation in order to save code size in the
|
||||
// generated parsing code.
|
||||
inline ::std::string** UnsafeRawStringPointer() {
|
||||
return &ptr_;
|
||||
}
|
||||
|
||||
inline bool IsDefault(const ::std::string* default_value) const {
|
||||
return ptr_ == default_value;
|
||||
inline bool IsDefault(const std::string* default_value) const {
|
||||
// Relies on the fact that kPtrTagString == 0, so if IsString(), ptr_ is the
|
||||
// actual std::string pointer (and if !IsString(), ptr_ will never be equal
|
||||
// to any aligned |default_value| pointer). The key is that we want to avoid
|
||||
// masking in the fastpath const-pointer Get() case for non-arena code.
|
||||
return tagged_ptr_.UnsafeGet() == default_value;
|
||||
}
|
||||
|
||||
private:
|
||||
::std::string* ptr_;
|
||||
TaggedPtr<std::string> tagged_ptr_;
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
void CreateInstance(::google::protobuf::Arena* arena,
|
||||
const ::std::string* initial_value) {
|
||||
GOOGLE_DCHECK(initial_value != NULL);
|
||||
ptr_ = new ::std::string(*initial_value);
|
||||
if (arena != NULL) {
|
||||
arena->Own(ptr_);
|
||||
}
|
||||
}
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
void CreateInstanceNoArena(const ::std::string* initial_value) {
|
||||
GOOGLE_DCHECK(initial_value != NULL);
|
||||
ptr_ = new ::std::string(*initial_value);
|
||||
bool IsDonatedString() const { return false; }
|
||||
|
||||
// Swaps tagged pointer without debug hardening. This is to allow python
|
||||
// protobuf to maintain pointer stability even in DEBUG builds.
|
||||
inline PROTOBUF_NDEBUG_INLINE static void UnsafeShallowSwap(
|
||||
ArenaStringPtr* rhs, ArenaStringPtr* lhs) {
|
||||
std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_);
|
||||
}
|
||||
|
||||
friend class ::google::protobuf::internal::SwapFieldHelper;
|
||||
|
||||
// Slow paths.
|
||||
|
||||
// MutableSlow requires that !IsString() || IsDefault
|
||||
// Variadic to support 0 args for EmptyDefault and 1 arg for LazyString.
|
||||
template <typename... Lazy>
|
||||
std::string* MutableSlow(::google::protobuf::Arena* arena, const Lazy&... lazy_default);
|
||||
|
||||
// Sets value to a newly allocated string and returns it
|
||||
std::string* SetAndReturnNewString();
|
||||
|
||||
// Destroys the non-default string value out-of-line
|
||||
void DestroyNoArenaSlowPath();
|
||||
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
inline void ArenaStringPtr::UnsafeSetDefault(const std::string* value) {
|
||||
tagged_ptr_.Set(const_cast<std::string*>(value));
|
||||
}
|
||||
|
||||
// Make sure rhs_arena allocated rhs, and lhs_arena allocated lhs.
|
||||
inline PROTOBUF_NDEBUG_INLINE void ArenaStringPtr::InternalSwap( //
|
||||
const std::string* default_value, //
|
||||
ArenaStringPtr* rhs, Arena* rhs_arena, //
|
||||
ArenaStringPtr* lhs, Arena* lhs_arena) {
|
||||
// Silence unused variable warnings in release buildls.
|
||||
(void)default_value;
|
||||
(void)rhs_arena;
|
||||
(void)lhs_arena;
|
||||
std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_);
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
auto force_realloc = [default_value](ArenaStringPtr* p, Arena* arena) {
|
||||
if (p->IsDefault(default_value)) return;
|
||||
std::string* old_value = p->tagged_ptr_.Get();
|
||||
std::string* new_value =
|
||||
p->IsDonatedString()
|
||||
? Arena::Create<std::string>(arena, *old_value)
|
||||
: Arena::Create<std::string>(arena, std::move(*old_value));
|
||||
if (arena == nullptr) delete old_value;
|
||||
p->tagged_ptr_.Set(new_value);
|
||||
};
|
||||
// Because, at this point, tagged_ptr_ has been swapped, arena should also be
|
||||
// swapped.
|
||||
force_realloc(lhs, rhs_arena);
|
||||
force_realloc(rhs, lhs_arena);
|
||||
#endif // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::ClearNonDefaultToEmpty() {
|
||||
// Unconditionally mask away the tag.
|
||||
tagged_ptr_.Get()->clear();
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
inline void ArenaStringPtr::AssignWithDefault(const ::std::string* default_value,
|
||||
ArenaStringPtr value) {
|
||||
const ::std::string* me = *UnsafeRawStringPointer();
|
||||
const ::std::string* other = *value.UnsafeRawStringPointer();
|
||||
// If the pointers are the same then do nothing.
|
||||
if (me != other) {
|
||||
SetNoArena(default_value, value.GetNoArena());
|
||||
inline std::string* ArenaStringPtr::MutableNoArenaNoDefault(
|
||||
const std::string* default_value) {
|
||||
// VERY IMPORTANT for performance and code size: this will reduce to a member
|
||||
// variable load, a pointer check (against |default_value|, in practice a
|
||||
// static global) and a branch to the slowpath (which calls operator new and
|
||||
// the ctor). DO NOT add any tagged-pointer operations here.
|
||||
if (IsDefault(default_value)) {
|
||||
return SetAndReturnNewString();
|
||||
} else {
|
||||
return UnsafeMutablePointer();
|
||||
}
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::DestroyNoArena(const std::string* default_value) {
|
||||
if (!IsDefault(default_value)) {
|
||||
DestroyNoArenaSlowPath();
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string* ArenaStringPtr::UnsafeMutablePointer() {
|
||||
GOOGLE_DCHECK(!tagged_ptr_.IsTagged());
|
||||
GOOGLE_DCHECK(tagged_ptr_.UnsafeGet() != nullptr);
|
||||
return tagged_ptr_.UnsafeGet();
|
||||
}
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ARENASTRING_H__
|
||||
|
||||
+3016
-2128
File diff suppressed because it is too large
Load Diff
+722
-442
File diff suppressed because it is too large
Load Diff
+6573
-9605
File diff suppressed because it is too large
Load Diff
+10042
-6773
File diff suppressed because it is too large
Load Diff
+638
-154
File diff suppressed because it is too large
Load Diff
+98
-90
@@ -44,6 +44,12 @@
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
@@ -62,27 +68,27 @@ class MergedDescriptorDatabase;
|
||||
// calling DescriptorPool::BuildFile() for each one. Instead, a DescriptorPool
|
||||
// can be created which wraps a DescriptorDatabase and only builds particular
|
||||
// descriptors when they are needed.
|
||||
class LIBPROTOBUF_EXPORT DescriptorDatabase {
|
||||
class PROTOBUF_EXPORT DescriptorDatabase {
|
||||
public:
|
||||
inline DescriptorDatabase() {}
|
||||
virtual ~DescriptorDatabase();
|
||||
|
||||
// Find a file by file name. Fills in in *output and returns true if found.
|
||||
// Otherwise, returns false, leaving the contents of *output undefined.
|
||||
virtual bool FindFileByName(const string& filename,
|
||||
virtual bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) = 0;
|
||||
|
||||
// Find the file that declares the given fully-qualified symbol name.
|
||||
// If found, fills in *output and returns true, otherwise returns false
|
||||
// and leaves *output undefined.
|
||||
virtual bool FindFileContainingSymbol(const string& symbol_name,
|
||||
virtual bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) = 0;
|
||||
|
||||
// Find the file which defines an extension extending the given message type
|
||||
// with the given field number. If found, fills in *output and returns true,
|
||||
// otherwise returns false and leaves *output undefined. containing_type
|
||||
// must be a fully-qualified type name.
|
||||
virtual bool FindFileContainingExtension(const string& containing_type,
|
||||
virtual bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output) = 0;
|
||||
|
||||
@@ -96,7 +102,7 @@ class LIBPROTOBUF_EXPORT DescriptorDatabase {
|
||||
//
|
||||
// This method has a default implementation that always returns
|
||||
// false.
|
||||
virtual bool FindAllExtensionNumbers(const string& /* extendee_type */,
|
||||
virtual bool FindAllExtensionNumbers(const std::string& /* extendee_type */,
|
||||
std::vector<int>* /* output */) {
|
||||
return false;
|
||||
}
|
||||
@@ -110,10 +116,24 @@ class LIBPROTOBUF_EXPORT DescriptorDatabase {
|
||||
//
|
||||
// This method has a default implementation that always returns
|
||||
// false.
|
||||
virtual bool FindAllFileNames(std::vector<string>* output) {
|
||||
virtual bool FindAllFileNames(std::vector<std::string>* /*output*/) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finds the package names and appends them to the output in an
|
||||
// undefined order. This method is best-effort: it's not guaranteed that the
|
||||
// database will find all packages. Returns true if the database supports
|
||||
// searching all package names, otherwise returns false and leaves output
|
||||
// unchanged.
|
||||
bool FindAllPackageNames(std::vector<std::string>* output);
|
||||
|
||||
// Finds the message names and appends them to the output in an
|
||||
// undefined order. This method is best-effort: it's not guaranteed that the
|
||||
// database will find all messages. Returns true if the database supports
|
||||
// searching all message names, otherwise returns false and leaves output
|
||||
// unchanged.
|
||||
bool FindAllMessageNames(std::vector<std::string>* output);
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorDatabase);
|
||||
};
|
||||
@@ -139,10 +159,10 @@ class LIBPROTOBUF_EXPORT DescriptorDatabase {
|
||||
// FileDescriptor::CopyTo()) will always use fully-qualified names for all
|
||||
// types. You only need to worry if you are constructing FileDescriptorProtos
|
||||
// yourself, or are calling compiler::Parser directly.
|
||||
class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
|
||||
class PROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
SimpleDescriptorDatabase();
|
||||
~SimpleDescriptorDatabase();
|
||||
~SimpleDescriptorDatabase() override;
|
||||
|
||||
// Adds the FileDescriptorProto to the database, making a copy. The object
|
||||
// can be deleted after Add() returns. Returns false if the file conflicted
|
||||
@@ -154,20 +174,19 @@ class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
|
||||
bool AddAndOwn(const FileDescriptorProto* file);
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const string& filename,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingSymbol(const string& symbol_name,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingExtension(const string& containing_type,
|
||||
bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output);
|
||||
bool FindAllExtensionNumbers(const string& extendee_type,
|
||||
std::vector<int>* output);
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindAllExtensionNumbers(const std::string& extendee_type,
|
||||
std::vector<int>* output) override;
|
||||
|
||||
bool FindAllFileNames(std::vector<std::string>* output) override;
|
||||
|
||||
private:
|
||||
// So that it can use DescriptorIndex.
|
||||
friend class EncodedDescriptorDatabase;
|
||||
|
||||
// An index mapping file names, symbol names, and extension numbers to
|
||||
// some sort of values.
|
||||
template <typename Value>
|
||||
@@ -175,24 +194,24 @@ class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
// Helpers to recursively add particular descriptors and all their contents
|
||||
// to the index.
|
||||
bool AddFile(const FileDescriptorProto& file,
|
||||
Value value);
|
||||
bool AddSymbol(const string& name, Value value);
|
||||
bool AddNestedExtensions(const DescriptorProto& message_type,
|
||||
Value value);
|
||||
bool AddExtension(const FieldDescriptorProto& field,
|
||||
Value value);
|
||||
bool AddFile(const FileDescriptorProto& file, Value value);
|
||||
bool AddSymbol(const std::string& name, Value value);
|
||||
bool AddNestedExtensions(const std::string& filename,
|
||||
const DescriptorProto& message_type, Value value);
|
||||
bool AddExtension(const std::string& filename,
|
||||
const FieldDescriptorProto& field, Value value);
|
||||
|
||||
Value FindFile(const string& filename);
|
||||
Value FindSymbol(const string& name);
|
||||
Value FindExtension(const string& containing_type, int field_number);
|
||||
bool FindAllExtensionNumbers(const string& containing_type,
|
||||
Value FindFile(const std::string& filename);
|
||||
Value FindSymbol(const std::string& name);
|
||||
Value FindExtension(const std::string& containing_type, int field_number);
|
||||
bool FindAllExtensionNumbers(const std::string& containing_type,
|
||||
std::vector<int>* output);
|
||||
void FindAllFileNames(std::vector<std::string>* output);
|
||||
|
||||
private:
|
||||
std::map<string, Value> by_name_;
|
||||
std::map<string, Value> by_symbol_;
|
||||
std::map<std::pair<string, int>, Value> by_extension_;
|
||||
std::map<std::string, Value> by_name_;
|
||||
std::map<std::string, Value> by_symbol_;
|
||||
std::map<std::pair<std::string, int>, Value> by_extension_;
|
||||
|
||||
// Invariant: The by_symbol_ map does not contain any symbols which are
|
||||
// prefixes of other symbols in the map. For example, "foo.bar" is a
|
||||
@@ -214,7 +233,7 @@ class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
|
||||
// will find it. Proof:
|
||||
// 1) Define the "search key" to be the key we are looking for, the "found
|
||||
// key" to be the key found in step (1), and the "match key" to be the
|
||||
// key which actually matches the serach key (i.e. the key we're trying
|
||||
// key which actually matches the search key (i.e. the key we're trying
|
||||
// to find).
|
||||
// 2) The found key must be less than or equal to the search key by
|
||||
// definition.
|
||||
@@ -244,30 +263,14 @@ class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
|
||||
// That symbol cannot be a super-symbol of the search key since if it were,
|
||||
// then it would be a match, and we're assuming the match key doesn't exist.
|
||||
// Therefore, step 2 will correctly return no match.
|
||||
|
||||
// Find the last entry in the by_symbol_ map whose key is less than or
|
||||
// equal to the given name.
|
||||
typename std::map<string, Value>::iterator FindLastLessOrEqual(
|
||||
const string& name);
|
||||
|
||||
// True if either the arguments are equal or super_symbol identifies a
|
||||
// parent symbol of sub_symbol (e.g. "foo.bar" is a parent of
|
||||
// "foo.bar.baz", but not a parent of "foo.barbaz").
|
||||
bool IsSubSymbol(const string& sub_symbol, const string& super_symbol);
|
||||
|
||||
// Returns true if and only if all characters in the name are alphanumerics,
|
||||
// underscores, or periods.
|
||||
bool ValidateSymbolName(const string& name);
|
||||
};
|
||||
|
||||
|
||||
DescriptorIndex<const FileDescriptorProto*> index_;
|
||||
std::vector<const FileDescriptorProto*> files_to_delete_;
|
||||
std::vector<std::unique_ptr<const FileDescriptorProto>> files_to_delete_;
|
||||
|
||||
// If file is non-NULL, copy it into *output and return true, otherwise
|
||||
// If file is non-nullptr, copy it into *output and return true, otherwise
|
||||
// return false.
|
||||
bool MaybeCopy(const FileDescriptorProto* file,
|
||||
FileDescriptorProto* output);
|
||||
bool MaybeCopy(const FileDescriptorProto* file, FileDescriptorProto* output);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleDescriptorDatabase);
|
||||
};
|
||||
@@ -277,10 +280,10 @@ class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
|
||||
//
|
||||
// The same caveats regarding FindFileContainingExtension() apply as with
|
||||
// SimpleDescriptorDatabase.
|
||||
class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
|
||||
class PROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
EncodedDescriptorDatabase();
|
||||
~EncodedDescriptorDatabase();
|
||||
~EncodedDescriptorDatabase() override;
|
||||
|
||||
// Adds the FileDescriptorProto to the database. The descriptor is provided
|
||||
// in encoded form. The database does not make a copy of the bytes, nor
|
||||
@@ -295,27 +298,30 @@ class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
|
||||
bool AddCopy(const void* encoded_file_descriptor, int size);
|
||||
|
||||
// Like FindFileContainingSymbol but returns only the name of the file.
|
||||
bool FindNameOfFileContainingSymbol(const string& symbol_name,
|
||||
string* output);
|
||||
bool FindNameOfFileContainingSymbol(const std::string& symbol_name,
|
||||
std::string* output);
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const string& filename,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingSymbol(const string& symbol_name,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingExtension(const string& containing_type,
|
||||
bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output);
|
||||
bool FindAllExtensionNumbers(const string& extendee_type,
|
||||
std::vector<int>* output);
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindAllExtensionNumbers(const std::string& extendee_type,
|
||||
std::vector<int>* output) override;
|
||||
bool FindAllFileNames(std::vector<std::string>* output) override;
|
||||
|
||||
private:
|
||||
SimpleDescriptorDatabase::DescriptorIndex<std::pair<const void*, int> >
|
||||
index_;
|
||||
class DescriptorIndex;
|
||||
// Keep DescriptorIndex by pointer to hide the implementation to keep a
|
||||
// cleaner header.
|
||||
std::unique_ptr<DescriptorIndex> index_;
|
||||
std::vector<void*> files_to_delete_;
|
||||
|
||||
// If encoded_file.first is non-NULL, parse the data into *output and return
|
||||
// true, otherwise return false.
|
||||
// If encoded_file.first is non-nullptr, parse the data into *output and
|
||||
// return true, otherwise return false.
|
||||
bool MaybeParse(std::pair<const void*, int> encoded_file,
|
||||
FileDescriptorProto* output);
|
||||
|
||||
@@ -323,21 +329,21 @@ class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
|
||||
};
|
||||
|
||||
// A DescriptorDatabase that fetches files from a given pool.
|
||||
class LIBPROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase {
|
||||
class PROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
explicit DescriptorPoolDatabase(const DescriptorPool& pool);
|
||||
~DescriptorPoolDatabase();
|
||||
~DescriptorPoolDatabase() override;
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const string& filename,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingSymbol(const string& symbol_name,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingExtension(const string& containing_type,
|
||||
bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output);
|
||||
bool FindAllExtensionNumbers(const string& extendee_type,
|
||||
std::vector<int>* output);
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindAllExtensionNumbers(const std::string& extendee_type,
|
||||
std::vector<int>* output) override;
|
||||
|
||||
private:
|
||||
const DescriptorPool& pool_;
|
||||
@@ -346,7 +352,7 @@ class LIBPROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase {
|
||||
|
||||
// A DescriptorDatabase that wraps two or more others. It first searches the
|
||||
// first database and, if that fails, tries the second, and so on.
|
||||
class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase {
|
||||
class PROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
// Merge just two databases. The sources remain property of the caller.
|
||||
MergedDescriptorDatabase(DescriptorDatabase* source1,
|
||||
@@ -356,20 +362,20 @@ class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase {
|
||||
// DescriptorDatabases need to stick around.
|
||||
explicit MergedDescriptorDatabase(
|
||||
const std::vector<DescriptorDatabase*>& sources);
|
||||
~MergedDescriptorDatabase();
|
||||
~MergedDescriptorDatabase() override;
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const string& filename,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingSymbol(const string& symbol_name,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingExtension(const string& containing_type,
|
||||
bool FindFileByName(const std::string& filename,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingSymbol(const std::string& symbol_name,
|
||||
FileDescriptorProto* output) override;
|
||||
bool FindFileContainingExtension(const std::string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output);
|
||||
FileDescriptorProto* output) override;
|
||||
// Merges the results of calling all databases. Returns true iff any
|
||||
// of the databases returned true.
|
||||
bool FindAllExtensionNumbers(const string& extendee_type,
|
||||
std::vector<int>* output);
|
||||
bool FindAllExtensionNumbers(const std::string& extendee_type,
|
||||
std::vector<int>* output) override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -378,6 +384,8 @@ class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase {
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
|
||||
|
||||
@@ -1,431 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/duration.proto
|
||||
|
||||
#include <google/protobuf/duration.pb.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// This is a temporary google only hack
|
||||
#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
|
||||
#include "third_party/protobuf/version.h"
|
||||
#endif
|
||||
// @@protoc_insertion_point(includes)
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class DurationDefaultTypeInternal {
|
||||
public:
|
||||
::google::protobuf::internal::ExplicitlyConstructed<Duration>
|
||||
_instance;
|
||||
} _Duration_default_instance_;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace protobuf_google_2fprotobuf_2fduration_2eproto {
|
||||
void InitDefaultsDurationImpl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
|
||||
::google::protobuf::internal::InitProtobufDefaultsForceUnique();
|
||||
#else
|
||||
::google::protobuf::internal::InitProtobufDefaults();
|
||||
#endif // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
|
||||
{
|
||||
void* ptr = &::google::protobuf::_Duration_default_instance_;
|
||||
new (ptr) ::google::protobuf::Duration();
|
||||
::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
|
||||
}
|
||||
::google::protobuf::Duration::InitAsDefaultInstance();
|
||||
}
|
||||
|
||||
void InitDefaultsDuration() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &InitDefaultsDurationImpl);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata file_level_metadata[1];
|
||||
|
||||
const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
~0u, // no _has_bits_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Duration, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Duration, seconds_),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Duration, nanos_),
|
||||
};
|
||||
static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ 0, -1, sizeof(::google::protobuf::Duration)},
|
||||
};
|
||||
|
||||
static ::google::protobuf::Message const * const file_default_instances[] = {
|
||||
reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::_Duration_default_instance_),
|
||||
};
|
||||
|
||||
void protobuf_AssignDescriptors() {
|
||||
AddDescriptors();
|
||||
::google::protobuf::MessageFactory* factory = NULL;
|
||||
AssignDescriptors(
|
||||
"google/protobuf/duration.proto", schemas, file_default_instances, TableStruct::offsets, factory,
|
||||
file_level_metadata, NULL, NULL);
|
||||
}
|
||||
|
||||
void protobuf_AssignDescriptorsOnce() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
|
||||
}
|
||||
|
||||
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD;
|
||||
void protobuf_RegisterTypes(const ::std::string&) {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1);
|
||||
}
|
||||
|
||||
void AddDescriptorsImpl() {
|
||||
InitDefaults();
|
||||
static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
"\n\036google/protobuf/duration.proto\022\017google"
|
||||
".protobuf\"*\n\010Duration\022\017\n\007seconds\030\001 \001(\003\022\r"
|
||||
"\n\005nanos\030\002 \001(\005B|\n\023com.google.protobufB\rDu"
|
||||
"rationProtoP\001Z*github.com/golang/protobu"
|
||||
"f/ptypes/duration\370\001\001\242\002\003GPB\252\002\036Google.Prot"
|
||||
"obuf.WellKnownTypesb\006proto3"
|
||||
};
|
||||
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
|
||||
descriptor, 227);
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
||||
"google/protobuf/duration.proto", &protobuf_RegisterTypes);
|
||||
}
|
||||
|
||||
void AddDescriptors() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
|
||||
}
|
||||
// Force AddDescriptors() to be called at dynamic initialization time.
|
||||
struct StaticDescriptorInitializer {
|
||||
StaticDescriptorInitializer() {
|
||||
AddDescriptors();
|
||||
}
|
||||
} static_descriptor_initializer;
|
||||
} // namespace protobuf_google_2fprotobuf_2fduration_2eproto
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
void Duration::InitAsDefaultInstance() {
|
||||
}
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
const int Duration::kSecondsFieldNumber;
|
||||
const int Duration::kNanosFieldNumber;
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
|
||||
Duration::Duration()
|
||||
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
|
||||
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
|
||||
::protobuf_google_2fprotobuf_2fduration_2eproto::InitDefaultsDuration();
|
||||
}
|
||||
SharedCtor();
|
||||
// @@protoc_insertion_point(constructor:google.protobuf.Duration)
|
||||
}
|
||||
Duration::Duration(::google::protobuf::Arena* arena)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(arena) {
|
||||
::protobuf_google_2fprotobuf_2fduration_2eproto::InitDefaultsDuration();
|
||||
SharedCtor();
|
||||
RegisterArenaDtor(arena);
|
||||
// @@protoc_insertion_point(arena_constructor:google.protobuf.Duration)
|
||||
}
|
||||
Duration::Duration(const Duration& from)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(NULL),
|
||||
_cached_size_(0) {
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
::memcpy(&seconds_, &from.seconds_,
|
||||
static_cast<size_t>(reinterpret_cast<char*>(&nanos_) -
|
||||
reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
|
||||
// @@protoc_insertion_point(copy_constructor:google.protobuf.Duration)
|
||||
}
|
||||
|
||||
void Duration::SharedCtor() {
|
||||
::memset(&seconds_, 0, static_cast<size_t>(
|
||||
reinterpret_cast<char*>(&nanos_) -
|
||||
reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
|
||||
_cached_size_ = 0;
|
||||
}
|
||||
|
||||
Duration::~Duration() {
|
||||
// @@protoc_insertion_point(destructor:google.protobuf.Duration)
|
||||
SharedDtor();
|
||||
}
|
||||
|
||||
void Duration::SharedDtor() {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() == NULL);
|
||||
}
|
||||
|
||||
void Duration::ArenaDtor(void* object) {
|
||||
Duration* _this = reinterpret_cast< Duration* >(object);
|
||||
(void)_this;
|
||||
}
|
||||
void Duration::RegisterArenaDtor(::google::protobuf::Arena* arena) {
|
||||
}
|
||||
void Duration::SetCachedSize(int size) const {
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
}
|
||||
const ::google::protobuf::Descriptor* Duration::descriptor() {
|
||||
::protobuf_google_2fprotobuf_2fduration_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return ::protobuf_google_2fprotobuf_2fduration_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
|
||||
}
|
||||
|
||||
const Duration& Duration::default_instance() {
|
||||
::protobuf_google_2fprotobuf_2fduration_2eproto::InitDefaultsDuration();
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
Duration* Duration::New(::google::protobuf::Arena* arena) const {
|
||||
return ::google::protobuf::Arena::CreateMessage<Duration>(arena);
|
||||
}
|
||||
|
||||
void Duration::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.Duration)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
::memset(&seconds_, 0, static_cast<size_t>(
|
||||
reinterpret_cast<char*>(&nanos_) -
|
||||
reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
|
||||
_internal_metadata_.Clear();
|
||||
}
|
||||
|
||||
bool Duration::MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) {
|
||||
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
|
||||
::google::protobuf::uint32 tag;
|
||||
// @@protoc_insertion_point(parse_start:google.protobuf.Duration)
|
||||
for (;;) {
|
||||
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
|
||||
tag = p.first;
|
||||
if (!p.second) goto handle_unusual;
|
||||
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
|
||||
// int64 seconds = 1;
|
||||
case 1: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
|
||||
|
||||
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
|
||||
::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
|
||||
input, &seconds_)));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// int32 nanos = 2;
|
||||
case 2: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
|
||||
|
||||
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
|
||||
::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
|
||||
input, &nanos_)));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
handle_unusual:
|
||||
if (tag == 0) {
|
||||
goto success;
|
||||
}
|
||||
DO_(::google::protobuf::internal::WireFormat::SkipField(
|
||||
input, tag, _internal_metadata_.mutable_unknown_fields()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success:
|
||||
// @@protoc_insertion_point(parse_success:google.protobuf.Duration)
|
||||
return true;
|
||||
failure:
|
||||
// @@protoc_insertion_point(parse_failure:google.protobuf.Duration)
|
||||
return false;
|
||||
#undef DO_
|
||||
}
|
||||
|
||||
void Duration::SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const {
|
||||
// @@protoc_insertion_point(serialize_start:google.protobuf.Duration)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// int64 seconds = 1;
|
||||
if (this->seconds() != 0) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteInt64(1, this->seconds(), output);
|
||||
}
|
||||
|
||||
// int32 nanos = 2;
|
||||
if (this->nanos() != 0) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->nanos(), output);
|
||||
}
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_end:google.protobuf.Duration)
|
||||
}
|
||||
|
||||
::google::protobuf::uint8* Duration::InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const {
|
||||
(void)deterministic; // Unused
|
||||
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Duration)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// int64 seconds = 1;
|
||||
if (this->seconds() != 0) {
|
||||
target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(1, this->seconds(), target);
|
||||
}
|
||||
|
||||
// int32 nanos = 2;
|
||||
if (this->nanos() != 0) {
|
||||
target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->nanos(), target);
|
||||
}
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Duration)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t Duration::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Duration)
|
||||
size_t total_size = 0;
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
total_size +=
|
||||
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()));
|
||||
}
|
||||
// int64 seconds = 1;
|
||||
if (this->seconds() != 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::Int64Size(
|
||||
this->seconds());
|
||||
}
|
||||
|
||||
// int32 nanos = 2;
|
||||
if (this->nanos() != 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::Int32Size(
|
||||
this->nanos());
|
||||
}
|
||||
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = cached_size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void Duration::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Duration)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
const Duration* source =
|
||||
::google::protobuf::internal::DynamicCastToGenerated<const Duration>(
|
||||
&from);
|
||||
if (source == NULL) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Duration)
|
||||
::google::protobuf::internal::ReflectionOps::Merge(from, this);
|
||||
} else {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Duration)
|
||||
MergeFrom(*source);
|
||||
}
|
||||
}
|
||||
|
||||
void Duration::MergeFrom(const Duration& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Duration)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
if (from.seconds() != 0) {
|
||||
set_seconds(from.seconds());
|
||||
}
|
||||
if (from.nanos() != 0) {
|
||||
set_nanos(from.nanos());
|
||||
}
|
||||
}
|
||||
|
||||
void Duration::CopyFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Duration)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
void Duration::CopyFrom(const Duration& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Duration)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool Duration::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Duration::Swap(Duration* other) {
|
||||
if (other == this) return;
|
||||
if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
Duration* temp = New(GetArenaNoVirtual());
|
||||
temp->MergeFrom(*other);
|
||||
other->CopyFrom(*this);
|
||||
InternalSwap(temp);
|
||||
if (GetArenaNoVirtual() == NULL) {
|
||||
delete temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
void Duration::UnsafeArenaSwap(Duration* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
|
||||
InternalSwap(other);
|
||||
}
|
||||
void Duration::InternalSwap(Duration* other) {
|
||||
using std::swap;
|
||||
swap(seconds_, other->seconds_);
|
||||
swap(nanos_, other->nanos_);
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
swap(_cached_size_, other->_cached_size_);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata Duration::GetMetadata() const {
|
||||
protobuf_google_2fprotobuf_2fduration_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return ::protobuf_google_2fprotobuf_2fduration_2eproto::file_level_metadata[kIndexInFileMessages];
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
-232
@@ -1,232 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/duration.proto
|
||||
|
||||
#ifndef PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED
|
||||
#define PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3005000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3005001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_table_driven.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace protobuf_google_2fprotobuf_2fduration_2eproto {
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct LIBPROTOBUF_EXPORT TableStruct {
|
||||
static const ::google::protobuf::internal::ParseTableField entries[];
|
||||
static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
|
||||
static const ::google::protobuf::internal::ParseTable schema[1];
|
||||
static const ::google::protobuf::internal::FieldMetadata field_metadata[];
|
||||
static const ::google::protobuf::internal::SerializationTable serialization_table[];
|
||||
static const ::google::protobuf::uint32 offsets[];
|
||||
};
|
||||
void LIBPROTOBUF_EXPORT AddDescriptors();
|
||||
void LIBPROTOBUF_EXPORT InitDefaultsDurationImpl();
|
||||
void LIBPROTOBUF_EXPORT InitDefaultsDuration();
|
||||
inline void LIBPROTOBUF_EXPORT InitDefaults() {
|
||||
InitDefaultsDuration();
|
||||
}
|
||||
} // namespace protobuf_google_2fprotobuf_2fduration_2eproto
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class Duration;
|
||||
class DurationDefaultTypeInternal;
|
||||
LIBPROTOBUF_EXPORT extern DurationDefaultTypeInternal _Duration_default_instance_;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class LIBPROTOBUF_EXPORT Duration : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Duration) */ {
|
||||
public:
|
||||
Duration();
|
||||
virtual ~Duration();
|
||||
|
||||
Duration(const Duration& from);
|
||||
|
||||
inline Duration& operator=(const Duration& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
#if LANG_CXX11
|
||||
Duration(Duration&& from) noexcept
|
||||
: Duration() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline Duration& operator=(Duration&& from) noexcept {
|
||||
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
|
||||
if (this != &from) InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
|
||||
return GetArenaNoVirtual();
|
||||
}
|
||||
inline void* GetMaybeArenaPointer() const PROTOBUF_FINAL {
|
||||
return MaybeArenaPtr();
|
||||
}
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const Duration& default_instance();
|
||||
|
||||
static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
|
||||
static inline const Duration* internal_default_instance() {
|
||||
return reinterpret_cast<const Duration*>(
|
||||
&_Duration_default_instance_);
|
||||
}
|
||||
static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
void UnsafeArenaSwap(Duration* other);
|
||||
void Swap(Duration* other);
|
||||
friend void swap(Duration& a, Duration& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline Duration* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
|
||||
Duration* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const Duration& from);
|
||||
void MergeFrom(const Duration& from);
|
||||
void Clear() PROTOBUF_FINAL;
|
||||
bool IsInitialized() const PROTOBUF_FINAL;
|
||||
|
||||
size_t ByteSizeLong() const PROTOBUF_FINAL;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
|
||||
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const PROTOBUF_FINAL;
|
||||
void InternalSwap(Duration* other);
|
||||
protected:
|
||||
explicit Duration(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return _internal_metadata_.arena();
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return _internal_metadata_.raw_arena_ptr();
|
||||
}
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// int64 seconds = 1;
|
||||
void clear_seconds();
|
||||
static const int kSecondsFieldNumber = 1;
|
||||
::google::protobuf::int64 seconds() const;
|
||||
void set_seconds(::google::protobuf::int64 value);
|
||||
|
||||
// int32 nanos = 2;
|
||||
void clear_nanos();
|
||||
static const int kNanosFieldNumber = 2;
|
||||
::google::protobuf::int32 nanos() const;
|
||||
void set_nanos(::google::protobuf::int32 value);
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.Duration)
|
||||
private:
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::google::protobuf::int64 seconds_;
|
||||
::google::protobuf::int32 nanos_;
|
||||
mutable int _cached_size_;
|
||||
friend struct ::protobuf_google_2fprotobuf_2fduration_2eproto::TableStruct;
|
||||
friend void ::protobuf_google_2fprotobuf_2fduration_2eproto::InitDefaultsDurationImpl();
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// Duration
|
||||
|
||||
// int64 seconds = 1;
|
||||
inline void Duration::clear_seconds() {
|
||||
seconds_ = GOOGLE_LONGLONG(0);
|
||||
}
|
||||
inline ::google::protobuf::int64 Duration::seconds() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Duration.seconds)
|
||||
return seconds_;
|
||||
}
|
||||
inline void Duration::set_seconds(::google::protobuf::int64 value) {
|
||||
|
||||
seconds_ = value;
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Duration.seconds)
|
||||
}
|
||||
|
||||
// int32 nanos = 2;
|
||||
inline void Duration::clear_nanos() {
|
||||
nanos_ = 0;
|
||||
}
|
||||
inline ::google::protobuf::int32 Duration::nanos() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Duration.nanos)
|
||||
return nanos_;
|
||||
}
|
||||
inline void Duration::set_nanos(::google::protobuf::int32 value) {
|
||||
|
||||
nanos_ = value;
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Duration.nanos)
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED
|
||||
+385
-396
File diff suppressed because it is too large
Load Diff
+42
-53
@@ -40,22 +40,27 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/stubs/mutex.h>
|
||||
#include <google/protobuf/reflection.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Defined in other files.
|
||||
class Descriptor; // descriptor.h
|
||||
class DescriptorPool; // descriptor.h
|
||||
class Descriptor; // descriptor.h
|
||||
class DescriptorPool; // descriptor.h
|
||||
|
||||
// Constructs implementations of Message which can emulate types which are not
|
||||
// known at compile-time.
|
||||
@@ -74,7 +79,7 @@ class DescriptorPool; // descriptor.h
|
||||
// encapsulates this "cache". All DynamicMessages of the same type created
|
||||
// from the same factory will share the same support data. Any Descriptors
|
||||
// used with a particular factory must outlive the factory.
|
||||
class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
|
||||
class PROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
|
||||
public:
|
||||
// Construct a DynamicMessageFactory that will search for extensions in
|
||||
// the DescriptorPool in which the extendee is defined.
|
||||
@@ -118,62 +123,44 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
|
||||
// outlive the DynamicMessageFactory.
|
||||
//
|
||||
// The method is thread-safe.
|
||||
const Message* GetPrototype(const Descriptor* type);
|
||||
const Message* GetPrototype(const Descriptor* type) override;
|
||||
|
||||
private:
|
||||
const DescriptorPool* pool_;
|
||||
bool delegate_to_generated_factory_;
|
||||
|
||||
// This struct just contains a hash_map. We can't #include <google/protobuf/stubs/hash.h> from
|
||||
// this header due to hacks needed for hash_map portability in the open source
|
||||
// release. Namely, stubs/hash.h, which defines hash_map portably, is not a
|
||||
// public header (for good reason), but dynamic_message.h is, and public
|
||||
// headers may only #include other public headers.
|
||||
struct PrototypeMap;
|
||||
google::protobuf::scoped_ptr<PrototypeMap> prototypes_;
|
||||
mutable Mutex prototypes_mutex_;
|
||||
struct TypeInfo;
|
||||
std::unordered_map<const Descriptor*, const TypeInfo*> prototypes_;
|
||||
mutable internal::WrappedMutex prototypes_mutex_;
|
||||
|
||||
friend class DynamicMessage;
|
||||
const Message* GetPrototypeNoLock(const Descriptor* type);
|
||||
|
||||
// Construct default oneof instance for reflection usage if oneof
|
||||
// is defined.
|
||||
static void ConstructDefaultOneofInstance(const Descriptor* type,
|
||||
const uint32 offsets[],
|
||||
void* default_oneof_instance);
|
||||
// Delete default oneof instance. Called by ~DynamicMessageFactory.
|
||||
static void DeleteDefaultOneofInstance(const Descriptor* type,
|
||||
const uint32 offsets[],
|
||||
const void* default_oneof_instance);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory);
|
||||
};
|
||||
|
||||
// Helper for computing a sorted list of map entries via reflection.
|
||||
class LIBPROTOBUF_EXPORT DynamicMapSorter {
|
||||
class PROTOBUF_EXPORT DynamicMapSorter {
|
||||
public:
|
||||
static std::vector<const Message*> Sort(const Message& message,
|
||||
int map_size,
|
||||
static std::vector<const Message*> Sort(const Message& message, int map_size,
|
||||
const Reflection* reflection,
|
||||
const FieldDescriptor* field) {
|
||||
std::vector<const Message*> result(static_cast<size_t>(map_size));
|
||||
const RepeatedPtrField<Message>& map_field =
|
||||
reflection->GetRepeatedPtrField<Message>(message, field);
|
||||
size_t i = 0;
|
||||
for (RepeatedPtrField<Message>::const_pointer_iterator it =
|
||||
map_field.pointer_begin(); it != map_field.pointer_end(); ) {
|
||||
result[i++] = *it++;
|
||||
std::vector<const Message*> result;
|
||||
result.reserve(map_size);
|
||||
RepeatedFieldRef<Message> map_field =
|
||||
reflection->GetRepeatedFieldRef<Message>(message, field);
|
||||
for (auto it = map_field.begin(); it != map_field.end(); ++it) {
|
||||
result.push_back(&*it);
|
||||
}
|
||||
GOOGLE_DCHECK_EQ(result.size(), i);
|
||||
MapEntryMessageComparator comparator(field->message_type());
|
||||
std::stable_sort(result.begin(), result.end(), comparator);
|
||||
// Complain if the keys aren't in ascending order.
|
||||
#ifndef NDEBUG
|
||||
for (size_t j = 1; j < static_cast<size_t>(map_size); j++) {
|
||||
if (!comparator(result[j - 1], result[j])) {
|
||||
GOOGLE_LOG(ERROR) << (comparator(result[j], result[j - 1]) ?
|
||||
"internal error in map key sorting" :
|
||||
"map keys are not unique");
|
||||
GOOGLE_LOG(ERROR) << (comparator(result[j], result[j - 1])
|
||||
? "internal error in map key sorting"
|
||||
: "map keys are not unique");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -181,7 +168,7 @@ class LIBPROTOBUF_EXPORT DynamicMapSorter {
|
||||
}
|
||||
|
||||
private:
|
||||
class LIBPROTOBUF_EXPORT MapEntryMessageComparator {
|
||||
class PROTOBUF_EXPORT MapEntryMessageComparator {
|
||||
public:
|
||||
explicit MapEntryMessageComparator(const Descriptor* descriptor)
|
||||
: field_(descriptor->field(0)) {}
|
||||
@@ -195,28 +182,28 @@ class LIBPROTOBUF_EXPORT DynamicMapSorter {
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_INT32: {
|
||||
int32 first = reflection->GetInt32(*a, field_);
|
||||
int32 second = reflection->GetInt32(*b, field_);
|
||||
int32_t first = reflection->GetInt32(*a, field_);
|
||||
int32_t second = reflection->GetInt32(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_INT64: {
|
||||
int64 first = reflection->GetInt64(*a, field_);
|
||||
int64 second = reflection->GetInt64(*b, field_);
|
||||
int64_t first = reflection->GetInt64(*a, field_);
|
||||
int64_t second = reflection->GetInt64(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_UINT32: {
|
||||
uint32 first = reflection->GetUInt32(*a, field_);
|
||||
uint32 second = reflection->GetUInt32(*b, field_);
|
||||
uint32_t first = reflection->GetUInt32(*a, field_);
|
||||
uint32_t second = reflection->GetUInt32(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_UINT64: {
|
||||
uint64 first = reflection->GetUInt64(*a, field_);
|
||||
uint64 second = reflection->GetUInt64(*b, field_);
|
||||
uint64_t first = reflection->GetUInt64(*a, field_);
|
||||
uint64_t second = reflection->GetUInt64(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_STRING: {
|
||||
string first = reflection->GetString(*a, field_);
|
||||
string second = reflection->GetString(*b, field_);
|
||||
std::string first = reflection->GetString(*a, field_);
|
||||
std::string second = reflection->GetString(*b, field_);
|
||||
return first < second;
|
||||
}
|
||||
default:
|
||||
@@ -231,6 +218,8 @@ class LIBPROTOBUF_EXPORT DynamicMapSorter {
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
|
||||
|
||||
-342
@@ -1,342 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/empty.proto
|
||||
|
||||
#include <google/protobuf/empty.pb.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// This is a temporary google only hack
|
||||
#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
|
||||
#include "third_party/protobuf/version.h"
|
||||
#endif
|
||||
// @@protoc_insertion_point(includes)
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class EmptyDefaultTypeInternal {
|
||||
public:
|
||||
::google::protobuf::internal::ExplicitlyConstructed<Empty>
|
||||
_instance;
|
||||
} _Empty_default_instance_;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace protobuf_google_2fprotobuf_2fempty_2eproto {
|
||||
void InitDefaultsEmptyImpl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
|
||||
::google::protobuf::internal::InitProtobufDefaultsForceUnique();
|
||||
#else
|
||||
::google::protobuf::internal::InitProtobufDefaults();
|
||||
#endif // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
|
||||
{
|
||||
void* ptr = &::google::protobuf::_Empty_default_instance_;
|
||||
new (ptr) ::google::protobuf::Empty();
|
||||
::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
|
||||
}
|
||||
::google::protobuf::Empty::InitAsDefaultInstance();
|
||||
}
|
||||
|
||||
void InitDefaultsEmpty() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &InitDefaultsEmptyImpl);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata file_level_metadata[1];
|
||||
|
||||
const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
~0u, // no _has_bits_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Empty, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
};
|
||||
static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ 0, -1, sizeof(::google::protobuf::Empty)},
|
||||
};
|
||||
|
||||
static ::google::protobuf::Message const * const file_default_instances[] = {
|
||||
reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::_Empty_default_instance_),
|
||||
};
|
||||
|
||||
void protobuf_AssignDescriptors() {
|
||||
AddDescriptors();
|
||||
::google::protobuf::MessageFactory* factory = NULL;
|
||||
AssignDescriptors(
|
||||
"google/protobuf/empty.proto", schemas, file_default_instances, TableStruct::offsets, factory,
|
||||
file_level_metadata, NULL, NULL);
|
||||
}
|
||||
|
||||
void protobuf_AssignDescriptorsOnce() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
|
||||
}
|
||||
|
||||
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD;
|
||||
void protobuf_RegisterTypes(const ::std::string&) {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1);
|
||||
}
|
||||
|
||||
void AddDescriptorsImpl() {
|
||||
InitDefaults();
|
||||
static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
"\n\033google/protobuf/empty.proto\022\017google.pr"
|
||||
"otobuf\"\007\n\005EmptyBv\n\023com.google.protobufB\n"
|
||||
"EmptyProtoP\001Z\'github.com/golang/protobuf"
|
||||
"/ptypes/empty\370\001\001\242\002\003GPB\252\002\036Google.Protobuf"
|
||||
".WellKnownTypesb\006proto3"
|
||||
};
|
||||
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
|
||||
descriptor, 183);
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
||||
"google/protobuf/empty.proto", &protobuf_RegisterTypes);
|
||||
}
|
||||
|
||||
void AddDescriptors() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
|
||||
}
|
||||
// Force AddDescriptors() to be called at dynamic initialization time.
|
||||
struct StaticDescriptorInitializer {
|
||||
StaticDescriptorInitializer() {
|
||||
AddDescriptors();
|
||||
}
|
||||
} static_descriptor_initializer;
|
||||
} // namespace protobuf_google_2fprotobuf_2fempty_2eproto
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
void Empty::InitAsDefaultInstance() {
|
||||
}
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
|
||||
Empty::Empty()
|
||||
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
|
||||
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
|
||||
::protobuf_google_2fprotobuf_2fempty_2eproto::InitDefaultsEmpty();
|
||||
}
|
||||
SharedCtor();
|
||||
// @@protoc_insertion_point(constructor:google.protobuf.Empty)
|
||||
}
|
||||
Empty::Empty(::google::protobuf::Arena* arena)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(arena) {
|
||||
::protobuf_google_2fprotobuf_2fempty_2eproto::InitDefaultsEmpty();
|
||||
SharedCtor();
|
||||
RegisterArenaDtor(arena);
|
||||
// @@protoc_insertion_point(arena_constructor:google.protobuf.Empty)
|
||||
}
|
||||
Empty::Empty(const Empty& from)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(NULL),
|
||||
_cached_size_(0) {
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
// @@protoc_insertion_point(copy_constructor:google.protobuf.Empty)
|
||||
}
|
||||
|
||||
void Empty::SharedCtor() {
|
||||
_cached_size_ = 0;
|
||||
}
|
||||
|
||||
Empty::~Empty() {
|
||||
// @@protoc_insertion_point(destructor:google.protobuf.Empty)
|
||||
SharedDtor();
|
||||
}
|
||||
|
||||
void Empty::SharedDtor() {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() == NULL);
|
||||
}
|
||||
|
||||
void Empty::ArenaDtor(void* object) {
|
||||
Empty* _this = reinterpret_cast< Empty* >(object);
|
||||
(void)_this;
|
||||
}
|
||||
void Empty::RegisterArenaDtor(::google::protobuf::Arena* arena) {
|
||||
}
|
||||
void Empty::SetCachedSize(int size) const {
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
}
|
||||
const ::google::protobuf::Descriptor* Empty::descriptor() {
|
||||
::protobuf_google_2fprotobuf_2fempty_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return ::protobuf_google_2fprotobuf_2fempty_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
|
||||
}
|
||||
|
||||
const Empty& Empty::default_instance() {
|
||||
::protobuf_google_2fprotobuf_2fempty_2eproto::InitDefaultsEmpty();
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
Empty* Empty::New(::google::protobuf::Arena* arena) const {
|
||||
return ::google::protobuf::Arena::CreateMessage<Empty>(arena);
|
||||
}
|
||||
|
||||
void Empty::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.Empty)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
_internal_metadata_.Clear();
|
||||
}
|
||||
|
||||
bool Empty::MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) {
|
||||
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
|
||||
::google::protobuf::uint32 tag;
|
||||
// @@protoc_insertion_point(parse_start:google.protobuf.Empty)
|
||||
for (;;) {
|
||||
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
|
||||
tag = p.first;
|
||||
if (!p.second) goto handle_unusual;
|
||||
handle_unusual:
|
||||
if (tag == 0) {
|
||||
goto success;
|
||||
}
|
||||
DO_(::google::protobuf::internal::WireFormat::SkipField(
|
||||
input, tag, _internal_metadata_.mutable_unknown_fields()));
|
||||
}
|
||||
success:
|
||||
// @@protoc_insertion_point(parse_success:google.protobuf.Empty)
|
||||
return true;
|
||||
failure:
|
||||
// @@protoc_insertion_point(parse_failure:google.protobuf.Empty)
|
||||
return false;
|
||||
#undef DO_
|
||||
}
|
||||
|
||||
void Empty::SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const {
|
||||
// @@protoc_insertion_point(serialize_start:google.protobuf.Empty)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_end:google.protobuf.Empty)
|
||||
}
|
||||
|
||||
::google::protobuf::uint8* Empty::InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const {
|
||||
(void)deterministic; // Unused
|
||||
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Empty)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Empty)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t Empty::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Empty)
|
||||
size_t total_size = 0;
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
total_size +=
|
||||
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()));
|
||||
}
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = cached_size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void Empty::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Empty)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
const Empty* source =
|
||||
::google::protobuf::internal::DynamicCastToGenerated<const Empty>(
|
||||
&from);
|
||||
if (source == NULL) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Empty)
|
||||
::google::protobuf::internal::ReflectionOps::Merge(from, this);
|
||||
} else {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Empty)
|
||||
MergeFrom(*source);
|
||||
}
|
||||
}
|
||||
|
||||
void Empty::MergeFrom(const Empty& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Empty)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
}
|
||||
|
||||
void Empty::CopyFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Empty)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
void Empty::CopyFrom(const Empty& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Empty)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool Empty::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Empty::Swap(Empty* other) {
|
||||
if (other == this) return;
|
||||
if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
Empty* temp = New(GetArenaNoVirtual());
|
||||
temp->MergeFrom(*other);
|
||||
other->CopyFrom(*this);
|
||||
InternalSwap(temp);
|
||||
if (GetArenaNoVirtual() == NULL) {
|
||||
delete temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
void Empty::UnsafeArenaSwap(Empty* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
|
||||
InternalSwap(other);
|
||||
}
|
||||
void Empty::InternalSwap(Empty* other) {
|
||||
using std::swap;
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
swap(_cached_size_, other->_cached_size_);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata Empty::GetMetadata() const {
|
||||
protobuf_google_2fprotobuf_2fempty_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return ::protobuf_google_2fprotobuf_2fempty_2eproto::file_level_metadata[kIndexInFileMessages];
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
-190
@@ -1,190 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/empty.proto
|
||||
|
||||
#ifndef PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED
|
||||
#define PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3005000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3005001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_table_driven.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace protobuf_google_2fprotobuf_2fempty_2eproto {
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct LIBPROTOBUF_EXPORT TableStruct {
|
||||
static const ::google::protobuf::internal::ParseTableField entries[];
|
||||
static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
|
||||
static const ::google::protobuf::internal::ParseTable schema[1];
|
||||
static const ::google::protobuf::internal::FieldMetadata field_metadata[];
|
||||
static const ::google::protobuf::internal::SerializationTable serialization_table[];
|
||||
static const ::google::protobuf::uint32 offsets[];
|
||||
};
|
||||
void LIBPROTOBUF_EXPORT AddDescriptors();
|
||||
void LIBPROTOBUF_EXPORT InitDefaultsEmptyImpl();
|
||||
void LIBPROTOBUF_EXPORT InitDefaultsEmpty();
|
||||
inline void LIBPROTOBUF_EXPORT InitDefaults() {
|
||||
InitDefaultsEmpty();
|
||||
}
|
||||
} // namespace protobuf_google_2fprotobuf_2fempty_2eproto
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class Empty;
|
||||
class EmptyDefaultTypeInternal;
|
||||
LIBPROTOBUF_EXPORT extern EmptyDefaultTypeInternal _Empty_default_instance_;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class LIBPROTOBUF_EXPORT Empty : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Empty) */ {
|
||||
public:
|
||||
Empty();
|
||||
virtual ~Empty();
|
||||
|
||||
Empty(const Empty& from);
|
||||
|
||||
inline Empty& operator=(const Empty& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
#if LANG_CXX11
|
||||
Empty(Empty&& from) noexcept
|
||||
: Empty() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline Empty& operator=(Empty&& from) noexcept {
|
||||
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
|
||||
if (this != &from) InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
|
||||
return GetArenaNoVirtual();
|
||||
}
|
||||
inline void* GetMaybeArenaPointer() const PROTOBUF_FINAL {
|
||||
return MaybeArenaPtr();
|
||||
}
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const Empty& default_instance();
|
||||
|
||||
static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
|
||||
static inline const Empty* internal_default_instance() {
|
||||
return reinterpret_cast<const Empty*>(
|
||||
&_Empty_default_instance_);
|
||||
}
|
||||
static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
void UnsafeArenaSwap(Empty* other);
|
||||
void Swap(Empty* other);
|
||||
friend void swap(Empty& a, Empty& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline Empty* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
|
||||
Empty* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const Empty& from);
|
||||
void MergeFrom(const Empty& from);
|
||||
void Clear() PROTOBUF_FINAL;
|
||||
bool IsInitialized() const PROTOBUF_FINAL;
|
||||
|
||||
size_t ByteSizeLong() const PROTOBUF_FINAL;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
|
||||
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const PROTOBUF_FINAL;
|
||||
void InternalSwap(Empty* other);
|
||||
protected:
|
||||
explicit Empty(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return _internal_metadata_.arena();
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return _internal_metadata_.raw_arena_ptr();
|
||||
}
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.Empty)
|
||||
private:
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
mutable int _cached_size_;
|
||||
friend struct ::protobuf_google_2fprotobuf_2fempty_2eproto::TableStruct;
|
||||
friend void ::protobuf_google_2fprotobuf_2fempty_2eproto::InitDefaultsEmptyImpl();
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// Empty
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED
|
||||
+49
-33
@@ -27,49 +27,65 @@
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_TIME_H_
|
||||
#define GOOGLE_PROTOBUF_STUBS_TIME_H_
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__
|
||||
#define GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
// clang-format off
|
||||
#include <google/protobuf/port_def.inc>
|
||||
// clang-format on
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
struct DateTime {
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
int hour;
|
||||
int minute;
|
||||
int second;
|
||||
// Wraps a variable whose constructor and destructor are explicitly
|
||||
// called. It is particularly useful for a global variable, without its
|
||||
// constructor and destructor run on start and end of the program lifetime.
|
||||
// This circumvents the initial construction order fiasco, while keeping
|
||||
// the address of the empty string a compile time constant.
|
||||
//
|
||||
// Pay special attention to the initialization state of the object.
|
||||
// 1. The object is "uninitialized" to begin with.
|
||||
// 2. Call Construct() or DefaultConstruct() only if the object is
|
||||
// uninitialized. After the call, the object becomes "initialized".
|
||||
// 3. Call get() and get_mutable() only if the object is initialized.
|
||||
// 4. Call Destruct() only if the object is initialized.
|
||||
// After the call, the object becomes uninitialized.
|
||||
template <typename T>
|
||||
class ExplicitlyConstructed {
|
||||
public:
|
||||
void DefaultConstruct() { new (&union_) T(); }
|
||||
|
||||
template <typename... Args>
|
||||
void Construct(Args&&... args) {
|
||||
new (&union_) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void Destruct() { get_mutable()->~T(); }
|
||||
|
||||
constexpr const T& get() const { return reinterpret_cast<const T&>(union_); }
|
||||
T* get_mutable() { return reinterpret_cast<T*>(&union_); }
|
||||
|
||||
private:
|
||||
union AlignedUnion {
|
||||
alignas(T) char space[sizeof(T)];
|
||||
int64_t align_to_int64;
|
||||
void* align_to_ptr;
|
||||
} union_;
|
||||
};
|
||||
|
||||
// Converts a timestamp (seconds elapsed since 1970-01-01T00:00:00, could be
|
||||
// negative to represent time before 1970-01-01) to DateTime. Returns false
|
||||
// if the timestamp is not in the range between 0001-01-01T00:00:00 and
|
||||
// 9999-12-31T23:59:59.
|
||||
bool LIBPROTOBUF_EXPORT SecondsToDateTime(int64 seconds, DateTime* time);
|
||||
// Converts DateTime to a timestamp (seconds since 1970-01-01T00:00:00).
|
||||
// Returns false if the DateTime is not valid or is not in the valid range.
|
||||
bool LIBPROTOBUF_EXPORT DateTimeToSeconds(const DateTime& time, int64* seconds);
|
||||
|
||||
void LIBPROTOBUF_EXPORT GetCurrentTime(int64* seconds, int32* nanos);
|
||||
|
||||
// Formats a time string in RFC3339 fromat.
|
||||
//
|
||||
// For example, "2015-05-20T13:29:35.120Z". For nanos, 0, 3, 6 or 9 fractional
|
||||
// digits will be used depending on how many are required to represent the exact
|
||||
// value.
|
||||
//
|
||||
// Note that "nanos" must in the range of [0, 999999999].
|
||||
string LIBPROTOBUF_EXPORT FormatTime(int64 seconds, int32 nanos);
|
||||
// Parses a time string. This method accepts RFC3339 date/time string with UTC
|
||||
// offset. For example, "2015-05-20T13:29:35.120-08:00".
|
||||
bool LIBPROTOBUF_EXPORT ParseTime(const string& value, int64* seconds, int32* nanos);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_TIME_H_
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__
|
||||
+1286
-848
File diff suppressed because it is too large
Load Diff
+764
-583
File diff suppressed because it is too large
Load Diff
+194
-462
@@ -35,42 +35,47 @@
|
||||
// Contains methods defined in extension_set.h which cannot be part of the
|
||||
// lite library because they use descriptors or reflection.
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/stubs/casts.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/extension_set_inl.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// A FieldSkipper used to store unknown MessageSet fields into UnknownFieldSet.
|
||||
class MessageSetFieldSkipper
|
||||
: public UnknownFieldSetFieldSkipper {
|
||||
class MessageSetFieldSkipper : public UnknownFieldSetFieldSkipper {
|
||||
public:
|
||||
explicit MessageSetFieldSkipper(UnknownFieldSet* unknown_fields)
|
||||
: UnknownFieldSetFieldSkipper(unknown_fields) {}
|
||||
virtual ~MessageSetFieldSkipper() {}
|
||||
~MessageSetFieldSkipper() override {}
|
||||
|
||||
virtual bool SkipMessageSetField(io::CodedInputStream* input,
|
||||
int field_number);
|
||||
};
|
||||
bool MessageSetFieldSkipper::SkipMessageSetField(
|
||||
io::CodedInputStream* input, int field_number) {
|
||||
uint32 length;
|
||||
bool MessageSetFieldSkipper::SkipMessageSetField(io::CodedInputStream* input,
|
||||
int field_number) {
|
||||
uint32_t length;
|
||||
if (!input->ReadVarint32(&length)) return false;
|
||||
if (unknown_fields_ == NULL) {
|
||||
if (unknown_fields_ == nullptr) {
|
||||
return input->Skip(length);
|
||||
} else {
|
||||
return input->ReadString(
|
||||
unknown_fields_->AddLengthDelimited(field_number), length);
|
||||
return input->ReadString(unknown_fields_->AddLengthDelimited(field_number),
|
||||
length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,9 +89,9 @@ class DescriptorPoolExtensionFinder : public ExtensionFinder {
|
||||
MessageFactory* factory,
|
||||
const Descriptor* containing_type)
|
||||
: pool_(pool), factory_(factory), containing_type_(containing_type) {}
|
||||
virtual ~DescriptorPoolExtensionFinder() {}
|
||||
~DescriptorPoolExtensionFinder() override {}
|
||||
|
||||
virtual bool Find(int number, ExtensionInfo* output);
|
||||
bool Find(int number, ExtensionInfo* output) override;
|
||||
|
||||
private:
|
||||
const DescriptorPool* pool_;
|
||||
@@ -95,16 +100,14 @@ class DescriptorPoolExtensionFinder : public ExtensionFinder {
|
||||
};
|
||||
|
||||
void ExtensionSet::AppendToList(
|
||||
const Descriptor* containing_type,
|
||||
const DescriptorPool* pool,
|
||||
const Descriptor* containing_type, const DescriptorPool* pool,
|
||||
std::vector<const FieldDescriptor*>* output) const {
|
||||
for (ExtensionMap::const_iterator iter = extensions_.begin();
|
||||
iter != extensions_.end(); ++iter) {
|
||||
ForEach([containing_type, pool, &output](int number, const Extension& ext) {
|
||||
bool has = false;
|
||||
if (iter->second.is_repeated) {
|
||||
has = iter->second.GetSize() > 0;
|
||||
if (ext.is_repeated) {
|
||||
has = ext.GetSize() > 0;
|
||||
} else {
|
||||
has = !iter->second.is_cleared;
|
||||
has = !ext.is_cleared;
|
||||
}
|
||||
|
||||
if (has) {
|
||||
@@ -113,14 +116,13 @@ void ExtensionSet::AppendToList(
|
||||
// initialized, so they might not even be constructed until
|
||||
// AppendToList() is called.
|
||||
|
||||
if (iter->second.descriptor == NULL) {
|
||||
output->push_back(pool->FindExtensionByNumber(
|
||||
containing_type, iter->first));
|
||||
if (ext.descriptor == nullptr) {
|
||||
output->push_back(pool->FindExtensionByNumber(containing_type, number));
|
||||
} else {
|
||||
output->push_back(iter->second.descriptor);
|
||||
output->push_back(ext.descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
inline FieldDescriptor::Type real_type(FieldType type) {
|
||||
@@ -138,26 +140,26 @@ inline WireFormatLite::FieldType field_type(FieldType type) {
|
||||
return static_cast<WireFormatLite::FieldType>(type);
|
||||
}
|
||||
|
||||
#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \
|
||||
GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \
|
||||
: FieldDescriptor::LABEL_OPTIONAL, \
|
||||
FieldDescriptor::LABEL_##LABEL); \
|
||||
#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \
|
||||
GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \
|
||||
: FieldDescriptor::LABEL_OPTIONAL, \
|
||||
FieldDescriptor::LABEL_##LABEL); \
|
||||
GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
|
||||
|
||||
const MessageLite& ExtensionSet::GetMessage(int number,
|
||||
const Descriptor* message_type,
|
||||
MessageFactory* factory) const {
|
||||
ExtensionMap::const_iterator iter = extensions_.find(number);
|
||||
if (iter == extensions_.end() || iter->second.is_cleared) {
|
||||
const Extension* extension = FindOrNull(number);
|
||||
if (extension == nullptr || extension->is_cleared) {
|
||||
// Not present. Return the default value.
|
||||
return *factory->GetPrototype(message_type);
|
||||
} else {
|
||||
GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
|
||||
if (iter->second.is_lazy) {
|
||||
return iter->second.lazymessage_value->GetMessage(
|
||||
*factory->GetPrototype(message_type));
|
||||
GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
|
||||
if (extension->is_lazy) {
|
||||
return extension->lazymessage_value->GetMessage(
|
||||
*factory->GetPrototype(message_type), arena_);
|
||||
} else {
|
||||
return *iter->second.message_value;
|
||||
return *extension->message_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,7 +183,7 @@ MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor,
|
||||
extension->is_cleared = false;
|
||||
if (extension->is_lazy) {
|
||||
return extension->lazymessage_value->MutableMessage(
|
||||
*factory->GetPrototype(descriptor->message_type()));
|
||||
*factory->GetPrototype(descriptor->message_type()), arena_);
|
||||
} else {
|
||||
return extension->message_value;
|
||||
}
|
||||
@@ -190,63 +192,64 @@ MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor,
|
||||
|
||||
MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
|
||||
MessageFactory* factory) {
|
||||
ExtensionMap::iterator iter = extensions_.find(descriptor->number());
|
||||
if (iter == extensions_.end()) {
|
||||
// Not present. Return NULL.
|
||||
return NULL;
|
||||
Extension* extension = FindOrNull(descriptor->number());
|
||||
if (extension == nullptr) {
|
||||
// Not present. Return nullptr.
|
||||
return nullptr;
|
||||
} else {
|
||||
GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
|
||||
MessageLite* ret = NULL;
|
||||
if (iter->second.is_lazy) {
|
||||
ret = iter->second.lazymessage_value->ReleaseMessage(
|
||||
*factory->GetPrototype(descriptor->message_type()));
|
||||
if (arena_ == NULL) {
|
||||
delete iter->second.lazymessage_value;
|
||||
GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
|
||||
MessageLite* ret = nullptr;
|
||||
if (extension->is_lazy) {
|
||||
ret = extension->lazymessage_value->ReleaseMessage(
|
||||
*factory->GetPrototype(descriptor->message_type()), arena_);
|
||||
if (arena_ == nullptr) {
|
||||
delete extension->lazymessage_value;
|
||||
}
|
||||
} else {
|
||||
if (arena_ != NULL) {
|
||||
ret = (iter->second.message_value)->New();
|
||||
ret->CheckTypeAndMergeFrom(*(iter->second.message_value));
|
||||
if (arena_ != nullptr) {
|
||||
ret = extension->message_value->New();
|
||||
ret->CheckTypeAndMergeFrom(*extension->message_value);
|
||||
} else {
|
||||
ret = iter->second.message_value;
|
||||
ret = extension->message_value;
|
||||
}
|
||||
}
|
||||
extensions_.erase(descriptor->number());
|
||||
Erase(descriptor->number());
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
MessageLite* ExtensionSet::UnsafeArenaReleaseMessage(
|
||||
const FieldDescriptor* descriptor, MessageFactory* factory) {
|
||||
ExtensionMap::iterator iter = extensions_.find(descriptor->number());
|
||||
if (iter == extensions_.end()) {
|
||||
// Not present. Return NULL.
|
||||
return NULL;
|
||||
Extension* extension = FindOrNull(descriptor->number());
|
||||
if (extension == nullptr) {
|
||||
// Not present. Return nullptr.
|
||||
return nullptr;
|
||||
} else {
|
||||
GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
|
||||
MessageLite* ret = NULL;
|
||||
if (iter->second.is_lazy) {
|
||||
ret = iter->second.lazymessage_value->UnsafeArenaReleaseMessage(
|
||||
*factory->GetPrototype(descriptor->message_type()));
|
||||
if (arena_ == NULL) {
|
||||
delete iter->second.lazymessage_value;
|
||||
GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
|
||||
MessageLite* ret = nullptr;
|
||||
if (extension->is_lazy) {
|
||||
ret = extension->lazymessage_value->UnsafeArenaReleaseMessage(
|
||||
*factory->GetPrototype(descriptor->message_type()), arena_);
|
||||
if (arena_ == nullptr) {
|
||||
delete extension->lazymessage_value;
|
||||
}
|
||||
} else {
|
||||
ret = iter->second.message_value;
|
||||
ret = extension->message_value;
|
||||
}
|
||||
extensions_.erase(descriptor->number());
|
||||
Erase(descriptor->number());
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionSet::Extension* ExtensionSet::MaybeNewRepeatedExtension(const FieldDescriptor* descriptor) {
|
||||
ExtensionSet::Extension* ExtensionSet::MaybeNewRepeatedExtension(
|
||||
const FieldDescriptor* descriptor) {
|
||||
Extension* extension;
|
||||
if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
|
||||
extension->type = descriptor->type();
|
||||
GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
|
||||
extension->is_repeated = true;
|
||||
extension->repeated_message_value =
|
||||
::google::protobuf::Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
|
||||
Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
|
||||
} else {
|
||||
GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
|
||||
}
|
||||
@@ -259,13 +262,15 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
|
||||
|
||||
// RepeatedPtrField<Message> does not know how to Add() since it cannot
|
||||
// allocate an abstract object, so we have to be tricky.
|
||||
MessageLite* result = extension->repeated_message_value
|
||||
->AddFromCleared<GenericTypeHandler<MessageLite> >();
|
||||
if (result == NULL) {
|
||||
MessageLite* result =
|
||||
reinterpret_cast<internal::RepeatedPtrFieldBase*>(
|
||||
extension->repeated_message_value)
|
||||
->AddFromCleared<GenericTypeHandler<MessageLite> >();
|
||||
if (result == nullptr) {
|
||||
const MessageLite* prototype;
|
||||
if (extension->repeated_message_value->size() == 0) {
|
||||
if (extension->repeated_message_value->empty()) {
|
||||
prototype = factory->GetPrototype(descriptor->message_type());
|
||||
GOOGLE_CHECK(prototype != NULL);
|
||||
GOOGLE_CHECK(prototype != nullptr);
|
||||
} else {
|
||||
prototype = &extension->repeated_message_value->Get(0);
|
||||
}
|
||||
@@ -282,15 +287,22 @@ void ExtensionSet::AddAllocatedMessage(const FieldDescriptor* descriptor,
|
||||
extension->repeated_message_value->AddAllocated(new_entry);
|
||||
}
|
||||
|
||||
void ExtensionSet::UnsafeArenaAddAllocatedMessage(
|
||||
const FieldDescriptor* descriptor, MessageLite* new_entry) {
|
||||
Extension* extension = MaybeNewRepeatedExtension(descriptor);
|
||||
|
||||
extension->repeated_message_value->UnsafeArenaAddAllocated(new_entry);
|
||||
}
|
||||
|
||||
static bool ValidateEnumUsingDescriptor(const void* arg, int number) {
|
||||
return reinterpret_cast<const EnumDescriptor*>(arg)
|
||||
->FindValueByNumber(number) != NULL;
|
||||
return reinterpret_cast<const EnumDescriptor*>(arg)->FindValueByNumber(
|
||||
number) != nullptr;
|
||||
}
|
||||
|
||||
bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
|
||||
const FieldDescriptor* extension =
|
||||
pool_->FindExtensionByNumber(containing_type_, number);
|
||||
if (extension == NULL) {
|
||||
if (extension == nullptr) {
|
||||
return false;
|
||||
} else {
|
||||
output->type = extension->type();
|
||||
@@ -298,10 +310,10 @@ bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
|
||||
output->is_packed = extension->options().packed();
|
||||
output->descriptor = extension;
|
||||
if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
||||
output->message_prototype =
|
||||
output->message_info.prototype =
|
||||
factory_->GetPrototype(extension->message_type());
|
||||
GOOGLE_CHECK(output->message_prototype != NULL)
|
||||
<< "Extension factory's GetPrototype() returned NULL for extension: "
|
||||
GOOGLE_CHECK(output->message_info.prototype != nullptr)
|
||||
<< "Extension factory's GetPrototype() returned nullptr; extension: "
|
||||
<< extension->full_name();
|
||||
} else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
|
||||
output->enum_validity_check.func = ValidateEnumUsingDescriptor;
|
||||
@@ -312,11 +324,63 @@ bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
|
||||
}
|
||||
}
|
||||
|
||||
bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
|
||||
|
||||
bool ExtensionSet::FindExtension(int wire_type, uint32_t field,
|
||||
const Message* containing_type,
|
||||
const internal::ParseContext* ctx,
|
||||
ExtensionInfo* extension,
|
||||
bool* was_packed_on_wire) {
|
||||
if (ctx->data().pool == nullptr) {
|
||||
GeneratedExtensionFinder finder(containing_type);
|
||||
if (!FindExtensionInfoFromFieldNumber(wire_type, field, &finder, extension,
|
||||
was_packed_on_wire)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
DescriptorPoolExtensionFinder finder(ctx->data().pool, ctx->data().factory,
|
||||
containing_type->GetDescriptor());
|
||||
if (!FindExtensionInfoFromFieldNumber(wire_type, field, &finder, extension,
|
||||
was_packed_on_wire)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* ExtensionSet::ParseField(uint64_t tag, const char* ptr,
|
||||
const Message* containing_type,
|
||||
internal::InternalMetadata* metadata,
|
||||
internal::ParseContext* ctx) {
|
||||
int number = tag >> 3;
|
||||
bool was_packed_on_wire;
|
||||
ExtensionInfo extension;
|
||||
if (!FindExtension(tag & 7, number, containing_type, ctx, &extension,
|
||||
&was_packed_on_wire)) {
|
||||
return UnknownFieldParse(
|
||||
tag, metadata->mutable_unknown_fields<UnknownFieldSet>(), ptr, ctx);
|
||||
}
|
||||
return ParseFieldWithExtensionInfo<UnknownFieldSet>(
|
||||
number, was_packed_on_wire, extension, metadata, ptr, ctx);
|
||||
}
|
||||
|
||||
const char* ExtensionSet::ParseFieldMaybeLazily(
|
||||
uint64_t tag, const char* ptr, const Message* containing_type,
|
||||
internal::InternalMetadata* metadata, internal::ParseContext* ctx) {
|
||||
return ParseField(tag, ptr, containing_type, metadata, ctx);
|
||||
}
|
||||
|
||||
const char* ExtensionSet::ParseMessageSetItem(
|
||||
const char* ptr, const Message* containing_type,
|
||||
internal::InternalMetadata* metadata, internal::ParseContext* ctx) {
|
||||
return ParseMessageSetItemTmpl<Message, UnknownFieldSet>(ptr, containing_type,
|
||||
metadata, ctx);
|
||||
}
|
||||
|
||||
bool ExtensionSet::ParseField(uint32_t tag, io::CodedInputStream* input,
|
||||
const Message* containing_type,
|
||||
UnknownFieldSet* unknown_fields) {
|
||||
UnknownFieldSetFieldSkipper skipper(unknown_fields);
|
||||
if (input->GetExtensionPool() == NULL) {
|
||||
if (input->GetExtensionPool() == nullptr) {
|
||||
GeneratedExtensionFinder finder(containing_type);
|
||||
return ParseField(tag, input, &finder, &skipper);
|
||||
} else {
|
||||
@@ -331,7 +395,7 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
|
||||
const Message* containing_type,
|
||||
UnknownFieldSet* unknown_fields) {
|
||||
MessageSetFieldSkipper skipper(unknown_fields);
|
||||
if (input->GetExtensionPool() == NULL) {
|
||||
if (input->GetExtensionPool() == nullptr) {
|
||||
GeneratedExtensionFinder finder(containing_type);
|
||||
return ParseMessageSet(input, &finder, &skipper);
|
||||
} else {
|
||||
@@ -347,14 +411,10 @@ int ExtensionSet::SpaceUsedExcludingSelf() const {
|
||||
}
|
||||
|
||||
size_t ExtensionSet::SpaceUsedExcludingSelfLong() const {
|
||||
size_t total_size =
|
||||
extensions_.size() * sizeof(ExtensionMap::value_type);
|
||||
for (ExtensionMap::const_iterator iter = extensions_.begin(),
|
||||
end = extensions_.end();
|
||||
iter != end;
|
||||
++iter) {
|
||||
total_size += iter->second.SpaceUsedExcludingSelfLong();
|
||||
}
|
||||
size_t total_size = Size() * sizeof(KeyValue);
|
||||
ForEach([&total_size](int /* number */, const Extension& ext) {
|
||||
total_size += ext.SpaceUsedExcludingSelfLong();
|
||||
});
|
||||
return total_size;
|
||||
}
|
||||
|
||||
@@ -373,15 +433,15 @@ size_t ExtensionSet::Extension::SpaceUsedExcludingSelfLong() const {
|
||||
repeated_##LOWERCASE##_value->SpaceUsedExcludingSelfLong(); \
|
||||
break
|
||||
|
||||
HANDLE_TYPE( INT32, int32);
|
||||
HANDLE_TYPE( INT64, int64);
|
||||
HANDLE_TYPE( UINT32, uint32);
|
||||
HANDLE_TYPE( UINT64, uint64);
|
||||
HANDLE_TYPE( FLOAT, float);
|
||||
HANDLE_TYPE( DOUBLE, double);
|
||||
HANDLE_TYPE( BOOL, bool);
|
||||
HANDLE_TYPE( ENUM, enum);
|
||||
HANDLE_TYPE( STRING, string);
|
||||
HANDLE_TYPE(INT32, int32_t);
|
||||
HANDLE_TYPE(INT64, int64_t);
|
||||
HANDLE_TYPE(UINT32, uint32_t);
|
||||
HANDLE_TYPE(UINT64, uint64_t);
|
||||
HANDLE_TYPE(FLOAT, float);
|
||||
HANDLE_TYPE(DOUBLE, double);
|
||||
HANDLE_TYPE(BOOL, bool);
|
||||
HANDLE_TYPE(ENUM, enum);
|
||||
HANDLE_TYPE(STRING, string);
|
||||
#undef HANDLE_TYPE
|
||||
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
@@ -389,9 +449,10 @@ size_t ExtensionSet::Extension::SpaceUsedExcludingSelfLong() const {
|
||||
// but MessageLite has no SpaceUsedLong(), so we must directly call
|
||||
// RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong() with a different
|
||||
// type handler.
|
||||
total_size +=
|
||||
sizeof(*repeated_message_value) +
|
||||
RepeatedMessage_SpaceUsedExcludingSelfLong(repeated_message_value);
|
||||
total_size += sizeof(*repeated_message_value) +
|
||||
RepeatedMessage_SpaceUsedExcludingSelfLong(
|
||||
reinterpret_cast<internal::RepeatedPtrFieldBase*>(
|
||||
repeated_message_value));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -415,218 +476,29 @@ size_t ExtensionSet::Extension::SpaceUsedExcludingSelfLong() const {
|
||||
return total_size;
|
||||
}
|
||||
|
||||
// The Serialize*ToArray methods are only needed in the heavy library, as
|
||||
// the lite library only generates SerializeWithCachedSizes.
|
||||
uint8* ExtensionSet::SerializeWithCachedSizesToArray(int start_field_number,
|
||||
int end_field_number,
|
||||
uint8* target) const {
|
||||
return InternalSerializeWithCachedSizesToArray(
|
||||
start_field_number, end_field_number,
|
||||
google::protobuf::io::CodedOutputStream::IsDefaultSerializationDeterministic(),
|
||||
target);
|
||||
uint8_t* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
|
||||
const MessageLite* extendee, uint8_t* target) const {
|
||||
io::EpsCopyOutputStream stream(
|
||||
target, MessageSetByteSize(),
|
||||
io::CodedOutputStream::IsDefaultSerializationDeterministic());
|
||||
return InternalSerializeMessageSetWithCachedSizesToArray(extendee, target,
|
||||
&stream);
|
||||
}
|
||||
|
||||
uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
|
||||
uint8* target) const {
|
||||
return InternalSerializeMessageSetWithCachedSizesToArray(
|
||||
google::protobuf::io::CodedOutputStream::IsDefaultSerializationDeterministic(),
|
||||
target);
|
||||
}
|
||||
|
||||
uint8* ExtensionSet::InternalSerializeWithCachedSizesToArray(
|
||||
int start_field_number, int end_field_number,
|
||||
bool deterministic, uint8* target) const {
|
||||
ExtensionMap::const_iterator iter;
|
||||
for (iter = extensions_.lower_bound(start_field_number);
|
||||
iter != extensions_.end() && iter->first < end_field_number;
|
||||
++iter) {
|
||||
target = iter->second.InternalSerializeFieldWithCachedSizesToArray(
|
||||
iter->first, deterministic, target);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
uint8* ExtensionSet::InternalSerializeMessageSetWithCachedSizesToArray(
|
||||
bool deterministic, uint8* target) const {
|
||||
ExtensionMap::const_iterator iter;
|
||||
for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
|
||||
target = iter->second.InternalSerializeMessageSetItemWithCachedSizesToArray(
|
||||
iter->first, deterministic, target);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
uint8* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray(
|
||||
int number, bool deterministic, uint8* target) const {
|
||||
if (is_repeated) {
|
||||
if (is_packed) {
|
||||
if (cached_size == 0) return target;
|
||||
|
||||
target = WireFormatLite::WriteTagToArray(number,
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target);
|
||||
target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target);
|
||||
|
||||
switch (real_type(type)) {
|
||||
#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
|
||||
case FieldDescriptor::TYPE_##UPPERCASE: \
|
||||
for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
|
||||
target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \
|
||||
repeated_##LOWERCASE##_value->Get(i), target); \
|
||||
} \
|
||||
break
|
||||
|
||||
HANDLE_TYPE( INT32, Int32, int32);
|
||||
HANDLE_TYPE( INT64, Int64, int64);
|
||||
HANDLE_TYPE( UINT32, UInt32, uint32);
|
||||
HANDLE_TYPE( UINT64, UInt64, uint64);
|
||||
HANDLE_TYPE( SINT32, SInt32, int32);
|
||||
HANDLE_TYPE( SINT64, SInt64, int64);
|
||||
HANDLE_TYPE( FIXED32, Fixed32, uint32);
|
||||
HANDLE_TYPE( FIXED64, Fixed64, uint64);
|
||||
HANDLE_TYPE(SFIXED32, SFixed32, int32);
|
||||
HANDLE_TYPE(SFIXED64, SFixed64, int64);
|
||||
HANDLE_TYPE( FLOAT, Float, float);
|
||||
HANDLE_TYPE( DOUBLE, Double, double);
|
||||
HANDLE_TYPE( BOOL, Bool, bool);
|
||||
HANDLE_TYPE( ENUM, Enum, enum);
|
||||
#undef HANDLE_TYPE
|
||||
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (real_type(type)) {
|
||||
#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
|
||||
case FieldDescriptor::TYPE_##UPPERCASE: \
|
||||
for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
|
||||
target = WireFormatLite::Write##CAMELCASE##ToArray(number, \
|
||||
repeated_##LOWERCASE##_value->Get(i), target); \
|
||||
} \
|
||||
break
|
||||
|
||||
HANDLE_TYPE( INT32, Int32, int32);
|
||||
HANDLE_TYPE( INT64, Int64, int64);
|
||||
HANDLE_TYPE( UINT32, UInt32, uint32);
|
||||
HANDLE_TYPE( UINT64, UInt64, uint64);
|
||||
HANDLE_TYPE( SINT32, SInt32, int32);
|
||||
HANDLE_TYPE( SINT64, SInt64, int64);
|
||||
HANDLE_TYPE( FIXED32, Fixed32, uint32);
|
||||
HANDLE_TYPE( FIXED64, Fixed64, uint64);
|
||||
HANDLE_TYPE(SFIXED32, SFixed32, int32);
|
||||
HANDLE_TYPE(SFIXED64, SFixed64, int64);
|
||||
HANDLE_TYPE( FLOAT, Float, float);
|
||||
HANDLE_TYPE( DOUBLE, Double, double);
|
||||
HANDLE_TYPE( BOOL, Bool, bool);
|
||||
HANDLE_TYPE( STRING, String, string);
|
||||
HANDLE_TYPE( BYTES, Bytes, string);
|
||||
HANDLE_TYPE( ENUM, Enum, enum);
|
||||
#undef HANDLE_TYPE
|
||||
#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
|
||||
case FieldDescriptor::TYPE_##UPPERCASE: \
|
||||
for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
|
||||
target = WireFormatLite::InternalWrite##CAMELCASE##ToArray( \
|
||||
number, repeated_##LOWERCASE##_value->Get(i), \
|
||||
deterministic, target); \
|
||||
} \
|
||||
break
|
||||
|
||||
HANDLE_TYPE( GROUP, Group, message);
|
||||
HANDLE_TYPE( MESSAGE, Message, message);
|
||||
#undef HANDLE_TYPE
|
||||
}
|
||||
}
|
||||
} else if (!is_cleared) {
|
||||
switch (real_type(type)) {
|
||||
#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \
|
||||
case FieldDescriptor::TYPE_##UPPERCASE: \
|
||||
target = WireFormatLite::Write##CAMELCASE##ToArray( \
|
||||
number, VALUE, target); \
|
||||
break
|
||||
|
||||
HANDLE_TYPE( INT32, Int32, int32_value);
|
||||
HANDLE_TYPE( INT64, Int64, int64_value);
|
||||
HANDLE_TYPE( UINT32, UInt32, uint32_value);
|
||||
HANDLE_TYPE( UINT64, UInt64, uint64_value);
|
||||
HANDLE_TYPE( SINT32, SInt32, int32_value);
|
||||
HANDLE_TYPE( SINT64, SInt64, int64_value);
|
||||
HANDLE_TYPE( FIXED32, Fixed32, uint32_value);
|
||||
HANDLE_TYPE( FIXED64, Fixed64, uint64_value);
|
||||
HANDLE_TYPE(SFIXED32, SFixed32, int32_value);
|
||||
HANDLE_TYPE(SFIXED64, SFixed64, int64_value);
|
||||
HANDLE_TYPE( FLOAT, Float, float_value);
|
||||
HANDLE_TYPE( DOUBLE, Double, double_value);
|
||||
HANDLE_TYPE( BOOL, Bool, bool_value);
|
||||
HANDLE_TYPE( STRING, String, *string_value);
|
||||
HANDLE_TYPE( BYTES, Bytes, *string_value);
|
||||
HANDLE_TYPE( ENUM, Enum, enum_value);
|
||||
HANDLE_TYPE( GROUP, Group, *message_value);
|
||||
#undef HANDLE_TYPE
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
if (is_lazy) {
|
||||
target = lazymessage_value->InternalWriteMessageToArray(
|
||||
number, deterministic, target);
|
||||
} else {
|
||||
target = WireFormatLite::InternalWriteMessageToArray(
|
||||
number, *message_value, deterministic, target);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
uint8*
|
||||
ExtensionSet::Extension::InternalSerializeMessageSetItemWithCachedSizesToArray(
|
||||
int number, bool deterministic, uint8* target) const {
|
||||
if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
|
||||
// Not a valid MessageSet extension, but serialize it the normal way.
|
||||
GOOGLE_LOG(WARNING) << "Invalid message set extension.";
|
||||
return InternalSerializeFieldWithCachedSizesToArray(number, deterministic,
|
||||
target);
|
||||
}
|
||||
|
||||
if (is_cleared) return target;
|
||||
|
||||
// Start group.
|
||||
target = io::CodedOutputStream::WriteTagToArray(
|
||||
WireFormatLite::kMessageSetItemStartTag, target);
|
||||
// Write type ID.
|
||||
target = WireFormatLite::WriteUInt32ToArray(
|
||||
WireFormatLite::kMessageSetTypeIdNumber, number, target);
|
||||
// Write message.
|
||||
if (is_lazy) {
|
||||
target = lazymessage_value->InternalWriteMessageToArray(
|
||||
WireFormatLite::kMessageSetMessageNumber, deterministic, target);
|
||||
} else {
|
||||
target = WireFormatLite::InternalWriteMessageToArray(
|
||||
WireFormatLite::kMessageSetMessageNumber, *message_value, deterministic,
|
||||
target);
|
||||
}
|
||||
// End group.
|
||||
target = io::CodedOutputStream::WriteTagToArray(
|
||||
WireFormatLite::kMessageSetItemEndTag, target);
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
bool ExtensionSet::ParseFieldMaybeLazily(
|
||||
int wire_type, int field_number, io::CodedInputStream* input,
|
||||
ExtensionFinder* extension_finder,
|
||||
MessageSetFieldSkipper* field_skipper) {
|
||||
return ParseField(WireFormatLite::MakeTag(
|
||||
field_number, static_cast<WireFormatLite::WireType>(wire_type)),
|
||||
input, extension_finder, field_skipper);
|
||||
ExtensionFinder* extension_finder, MessageSetFieldSkipper* field_skipper) {
|
||||
return ParseField(
|
||||
WireFormatLite::MakeTag(field_number,
|
||||
static_cast<WireFormatLite::WireType>(wire_type)),
|
||||
input, extension_finder, field_skipper);
|
||||
}
|
||||
|
||||
bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
|
||||
ExtensionFinder* extension_finder,
|
||||
MessageSetFieldSkipper* field_skipper) {
|
||||
while (true) {
|
||||
const uint32 tag = input->ReadTag();
|
||||
const uint32_t tag = input->ReadTag();
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return true;
|
||||
@@ -644,171 +516,31 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
|
||||
}
|
||||
}
|
||||
|
||||
bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
|
||||
const MessageLite* containing_type) {
|
||||
MessageSetFieldSkipper skipper(NULL);
|
||||
GeneratedExtensionFinder finder(containing_type);
|
||||
return ParseMessageSet(input, &finder, &skipper);
|
||||
}
|
||||
|
||||
bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
|
||||
ExtensionFinder* extension_finder,
|
||||
MessageSetFieldSkipper* field_skipper) {
|
||||
// TODO(kenton): It would be nice to share code between this and
|
||||
// WireFormatLite::ParseAndMergeMessageSetItem(), but I think the
|
||||
// differences would be hard to factor out.
|
||||
|
||||
// This method parses a group which should contain two fields:
|
||||
// required int32 type_id = 2;
|
||||
// required data message = 3;
|
||||
|
||||
uint32 last_type_id = 0;
|
||||
|
||||
// If we see message data before the type_id, we'll append it to this so
|
||||
// we can parse it later.
|
||||
string message_data;
|
||||
|
||||
while (true) {
|
||||
const uint32 tag = input->ReadTagNoLastTag();
|
||||
if (tag == 0) return false;
|
||||
|
||||
switch (tag) {
|
||||
case WireFormatLite::kMessageSetTypeIdTag: {
|
||||
uint32 type_id;
|
||||
if (!input->ReadVarint32(&type_id)) return false;
|
||||
last_type_id = type_id;
|
||||
|
||||
if (!message_data.empty()) {
|
||||
// We saw some message data before the type_id. Have to parse it
|
||||
// now.
|
||||
io::CodedInputStream sub_input(
|
||||
reinterpret_cast<const uint8*>(message_data.data()),
|
||||
message_data.size());
|
||||
if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
|
||||
last_type_id, &sub_input,
|
||||
extension_finder, field_skipper)) {
|
||||
return false;
|
||||
}
|
||||
message_data.clear();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WireFormatLite::kMessageSetMessageTag: {
|
||||
if (last_type_id == 0) {
|
||||
// We haven't seen a type_id yet. Append this data to message_data.
|
||||
string temp;
|
||||
uint32 length;
|
||||
if (!input->ReadVarint32(&length)) return false;
|
||||
if (!input->ReadString(&temp, length)) return false;
|
||||
io::StringOutputStream output_stream(&message_data);
|
||||
io::CodedOutputStream coded_output(&output_stream);
|
||||
coded_output.WriteVarint32(length);
|
||||
coded_output.WriteString(temp);
|
||||
} else {
|
||||
// Already saw type_id, so we can parse this directly.
|
||||
if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
|
||||
last_type_id, input,
|
||||
extension_finder, field_skipper)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WireFormatLite::kMessageSetItemEndTag: {
|
||||
return true;
|
||||
}
|
||||
|
||||
default: {
|
||||
if (!field_skipper->SkipField(input, tag)) return false;
|
||||
}
|
||||
struct MSFull {
|
||||
bool ParseField(int type_id, io::CodedInputStream* input) {
|
||||
return me->ParseFieldMaybeLazily(
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED, type_id, input,
|
||||
extension_finder, field_skipper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes(
|
||||
int number,
|
||||
io::CodedOutputStream* output) const {
|
||||
if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
|
||||
// Not a valid MessageSet extension, but serialize it the normal way.
|
||||
SerializeFieldWithCachedSizes(number, output);
|
||||
return;
|
||||
}
|
||||
bool SkipField(uint32_t tag, io::CodedInputStream* input) {
|
||||
return field_skipper->SkipField(input, tag);
|
||||
}
|
||||
|
||||
if (is_cleared) return;
|
||||
ExtensionSet* me;
|
||||
ExtensionFinder* extension_finder;
|
||||
MessageSetFieldSkipper* field_skipper;
|
||||
};
|
||||
|
||||
// Start group.
|
||||
output->WriteTag(WireFormatLite::kMessageSetItemStartTag);
|
||||
|
||||
// Write type ID.
|
||||
WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber,
|
||||
number,
|
||||
output);
|
||||
// Write message.
|
||||
if (is_lazy) {
|
||||
lazymessage_value->WriteMessage(
|
||||
WireFormatLite::kMessageSetMessageNumber, output);
|
||||
} else {
|
||||
WireFormatLite::WriteMessageMaybeToArray(
|
||||
WireFormatLite::kMessageSetMessageNumber,
|
||||
*message_value,
|
||||
output);
|
||||
}
|
||||
|
||||
// End group.
|
||||
output->WriteTag(WireFormatLite::kMessageSetItemEndTag);
|
||||
}
|
||||
|
||||
size_t ExtensionSet::Extension::MessageSetItemByteSize(int number) const {
|
||||
if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
|
||||
// Not a valid MessageSet extension, but compute the byte size for it the
|
||||
// normal way.
|
||||
return ByteSize(number);
|
||||
}
|
||||
|
||||
if (is_cleared) return 0;
|
||||
|
||||
size_t our_size = WireFormatLite::kMessageSetItemTagsSize;
|
||||
|
||||
// type_id
|
||||
our_size += io::CodedOutputStream::VarintSize32(number);
|
||||
|
||||
// message
|
||||
size_t message_size = 0;
|
||||
if (is_lazy) {
|
||||
message_size = lazymessage_value->ByteSize();
|
||||
} else {
|
||||
message_size = message_value->ByteSize();
|
||||
}
|
||||
|
||||
our_size += io::CodedOutputStream::VarintSize32(message_size);
|
||||
our_size += message_size;
|
||||
|
||||
return our_size;
|
||||
}
|
||||
|
||||
void ExtensionSet::SerializeMessageSetWithCachedSizes(
|
||||
io::CodedOutputStream* output) const {
|
||||
for (ExtensionMap::const_iterator iter = extensions_.begin();
|
||||
iter != extensions_.end(); ++iter) {
|
||||
iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output);
|
||||
}
|
||||
}
|
||||
|
||||
size_t ExtensionSet::MessageSetByteSize() const {
|
||||
size_t total_size = 0;
|
||||
|
||||
for (ExtensionMap::const_iterator iter = extensions_.begin();
|
||||
iter != extensions_.end(); ++iter) {
|
||||
total_size += iter->second.MessageSetItemByteSize(iter->first);
|
||||
}
|
||||
|
||||
return total_size;
|
||||
return ParseMessageSetItemImpl(input,
|
||||
MSFull{this, extension_finder, field_skipper});
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
|
||||
#define GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
|
||||
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
template <typename T>
|
||||
const char* ExtensionSet::ParseFieldWithExtensionInfo(
|
||||
int number, bool was_packed_on_wire, const ExtensionInfo& extension,
|
||||
InternalMetadata* metadata, const char* ptr, internal::ParseContext* ctx) {
|
||||
if (was_packed_on_wire) {
|
||||
switch (extension.type) {
|
||||
#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE) \
|
||||
case WireFormatLite::TYPE_##UPPERCASE: \
|
||||
return internal::Packed##CPP_CAMELCASE##Parser( \
|
||||
MutableRawRepeatedField(number, extension.type, extension.is_packed, \
|
||||
extension.descriptor), \
|
||||
ptr, ctx);
|
||||
HANDLE_TYPE(INT32, Int32);
|
||||
HANDLE_TYPE(INT64, Int64);
|
||||
HANDLE_TYPE(UINT32, UInt32);
|
||||
HANDLE_TYPE(UINT64, UInt64);
|
||||
HANDLE_TYPE(SINT32, SInt32);
|
||||
HANDLE_TYPE(SINT64, SInt64);
|
||||
HANDLE_TYPE(FIXED32, Fixed32);
|
||||
HANDLE_TYPE(FIXED64, Fixed64);
|
||||
HANDLE_TYPE(SFIXED32, SFixed32);
|
||||
HANDLE_TYPE(SFIXED64, SFixed64);
|
||||
HANDLE_TYPE(FLOAT, Float);
|
||||
HANDLE_TYPE(DOUBLE, Double);
|
||||
HANDLE_TYPE(BOOL, Bool);
|
||||
#undef HANDLE_TYPE
|
||||
|
||||
case WireFormatLite::TYPE_ENUM:
|
||||
return internal::PackedEnumParserArg<T>(
|
||||
MutableRawRepeatedField(number, extension.type, extension.is_packed,
|
||||
extension.descriptor),
|
||||
ptr, ctx, extension.enum_validity_check.func,
|
||||
extension.enum_validity_check.arg, metadata, number);
|
||||
case WireFormatLite::TYPE_STRING:
|
||||
case WireFormatLite::TYPE_BYTES:
|
||||
case WireFormatLite::TYPE_GROUP:
|
||||
case WireFormatLite::TYPE_MESSAGE:
|
||||
GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (extension.type) {
|
||||
#define HANDLE_VARINT_TYPE(UPPERCASE, CPP_CAMELCASE) \
|
||||
case WireFormatLite::TYPE_##UPPERCASE: { \
|
||||
uint64_t value; \
|
||||
ptr = VarintParse(ptr, &value); \
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); \
|
||||
if (extension.is_repeated) { \
|
||||
Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
|
||||
extension.is_packed, value, extension.descriptor); \
|
||||
} else { \
|
||||
Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
|
||||
extension.descriptor); \
|
||||
} \
|
||||
} break
|
||||
|
||||
HANDLE_VARINT_TYPE(INT32, Int32);
|
||||
HANDLE_VARINT_TYPE(INT64, Int64);
|
||||
HANDLE_VARINT_TYPE(UINT32, UInt32);
|
||||
HANDLE_VARINT_TYPE(UINT64, UInt64);
|
||||
HANDLE_VARINT_TYPE(BOOL, Bool);
|
||||
#undef HANDLE_VARINT_TYPE
|
||||
#define HANDLE_SVARINT_TYPE(UPPERCASE, CPP_CAMELCASE, SIZE) \
|
||||
case WireFormatLite::TYPE_##UPPERCASE: { \
|
||||
uint64_t val; \
|
||||
ptr = VarintParse(ptr, &val); \
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); \
|
||||
auto value = WireFormatLite::ZigZagDecode##SIZE(val); \
|
||||
if (extension.is_repeated) { \
|
||||
Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
|
||||
extension.is_packed, value, extension.descriptor); \
|
||||
} else { \
|
||||
Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
|
||||
extension.descriptor); \
|
||||
} \
|
||||
} break
|
||||
|
||||
HANDLE_SVARINT_TYPE(SINT32, Int32, 32);
|
||||
HANDLE_SVARINT_TYPE(SINT64, Int64, 64);
|
||||
#undef HANDLE_SVARINT_TYPE
|
||||
#define HANDLE_FIXED_TYPE(UPPERCASE, CPP_CAMELCASE, CPPTYPE) \
|
||||
case WireFormatLite::TYPE_##UPPERCASE: { \
|
||||
auto value = UnalignedLoad<CPPTYPE>(ptr); \
|
||||
ptr += sizeof(CPPTYPE); \
|
||||
if (extension.is_repeated) { \
|
||||
Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
|
||||
extension.is_packed, value, extension.descriptor); \
|
||||
} else { \
|
||||
Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
|
||||
extension.descriptor); \
|
||||
} \
|
||||
} break
|
||||
|
||||
HANDLE_FIXED_TYPE(FIXED32, UInt32, uint32_t);
|
||||
HANDLE_FIXED_TYPE(FIXED64, UInt64, uint64_t);
|
||||
HANDLE_FIXED_TYPE(SFIXED32, Int32, int32_t);
|
||||
HANDLE_FIXED_TYPE(SFIXED64, Int64, int64_t);
|
||||
HANDLE_FIXED_TYPE(FLOAT, Float, float);
|
||||
HANDLE_FIXED_TYPE(DOUBLE, Double, double);
|
||||
#undef HANDLE_FIXED_TYPE
|
||||
|
||||
case WireFormatLite::TYPE_ENUM: {
|
||||
uint64_t val;
|
||||
ptr = VarintParse(ptr, &val);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
int value = val;
|
||||
|
||||
if (!extension.enum_validity_check.func(
|
||||
extension.enum_validity_check.arg, value)) {
|
||||
WriteVarint(number, val, metadata->mutable_unknown_fields<T>());
|
||||
} else if (extension.is_repeated) {
|
||||
AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value,
|
||||
extension.descriptor);
|
||||
} else {
|
||||
SetEnum(number, WireFormatLite::TYPE_ENUM, value,
|
||||
extension.descriptor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WireFormatLite::TYPE_BYTES:
|
||||
case WireFormatLite::TYPE_STRING: {
|
||||
std::string* value =
|
||||
extension.is_repeated
|
||||
? AddString(number, WireFormatLite::TYPE_STRING,
|
||||
extension.descriptor)
|
||||
: MutableString(number, WireFormatLite::TYPE_STRING,
|
||||
extension.descriptor);
|
||||
int size = ReadSize(&ptr);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
return ctx->ReadString(ptr, size, value);
|
||||
}
|
||||
|
||||
case WireFormatLite::TYPE_GROUP: {
|
||||
MessageLite* value =
|
||||
extension.is_repeated
|
||||
? AddMessage(number, WireFormatLite::TYPE_GROUP,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor)
|
||||
: MutableMessage(number, WireFormatLite::TYPE_GROUP,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor);
|
||||
uint32_t tag = (number << 3) + WireFormatLite::WIRETYPE_START_GROUP;
|
||||
return ctx->ParseGroup(value, ptr, tag);
|
||||
}
|
||||
|
||||
case WireFormatLite::TYPE_MESSAGE: {
|
||||
MessageLite* value =
|
||||
extension.is_repeated
|
||||
? AddMessage(number, WireFormatLite::TYPE_MESSAGE,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor)
|
||||
: MutableMessage(number, WireFormatLite::TYPE_MESSAGE,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor);
|
||||
return ctx->ParseMessage(value, ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename Msg, typename T>
|
||||
const char* ExtensionSet::ParseMessageSetItemTmpl(
|
||||
const char* ptr, const Msg* extendee, internal::InternalMetadata* metadata,
|
||||
internal::ParseContext* ctx) {
|
||||
std::string payload;
|
||||
uint32_t type_id = 0;
|
||||
bool payload_read = false;
|
||||
while (!ctx->Done(&ptr)) {
|
||||
uint32_t tag = static_cast<uint8_t>(*ptr++);
|
||||
if (tag == WireFormatLite::kMessageSetTypeIdTag) {
|
||||
uint64_t tmp;
|
||||
ptr = ParseBigVarint(ptr, &tmp);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
type_id = tmp;
|
||||
if (payload_read) {
|
||||
ExtensionInfo extension;
|
||||
bool was_packed_on_wire;
|
||||
if (!FindExtension(2, type_id, extendee, ctx, &extension,
|
||||
&was_packed_on_wire)) {
|
||||
WriteLengthDelimited(type_id, payload,
|
||||
metadata->mutable_unknown_fields<T>());
|
||||
} else {
|
||||
MessageLite* value =
|
||||
extension.is_repeated
|
||||
? AddMessage(type_id, WireFormatLite::TYPE_MESSAGE,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor)
|
||||
: MutableMessage(type_id, WireFormatLite::TYPE_MESSAGE,
|
||||
*extension.message_info.prototype,
|
||||
extension.descriptor);
|
||||
|
||||
const char* p;
|
||||
// We can't use regular parse from string as we have to track
|
||||
// proper recursion depth and descriptor pools.
|
||||
ParseContext tmp_ctx(ctx->depth(), false, &p, payload);
|
||||
tmp_ctx.data().pool = ctx->data().pool;
|
||||
tmp_ctx.data().factory = ctx->data().factory;
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(value->_InternalParse(p, &tmp_ctx) &&
|
||||
tmp_ctx.EndedAtLimit());
|
||||
}
|
||||
type_id = 0;
|
||||
}
|
||||
} else if (tag == WireFormatLite::kMessageSetMessageTag) {
|
||||
if (type_id != 0) {
|
||||
ptr = ParseFieldMaybeLazily(static_cast<uint64_t>(type_id) * 8 + 2, ptr,
|
||||
extendee, metadata, ctx);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
|
||||
type_id = 0;
|
||||
} else {
|
||||
int32_t size = ReadSize(&ptr);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
ptr = ctx->ReadString(ptr, size, &payload);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
payload_read = true;
|
||||
}
|
||||
} else {
|
||||
ptr = ReadTag(ptr - 1, &tag);
|
||||
if (tag == 0 || (tag & 7) == 4) {
|
||||
ctx->SetLastTag(tag);
|
||||
return ptr;
|
||||
}
|
||||
ptr = ParseField(tag, ptr, extendee, metadata, ctx);
|
||||
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
|
||||
@@ -0,0 +1,172 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
|
||||
#define GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// A default/no-op implementation of message hooks.
|
||||
//
|
||||
// See go/statically-dispatched-message-hooks for details.
|
||||
template <typename Proto>
|
||||
struct NoOpAccessListener {
|
||||
// Number of fields are provided at compile time for the trackers to be able
|
||||
// to have stack allocated bitmaps for the fields. This is useful for
|
||||
// performance critical trackers. This is also to avoid cyclic dependencies
|
||||
// if the number of fields is needed.
|
||||
static constexpr int kFields = Proto::_kInternalFieldNumber;
|
||||
// Default constructor is called during the static global initialization of
|
||||
// the program.
|
||||
// We provide a pointer to extract the name of the proto not to get cyclic
|
||||
// dependencies on GetDescriptor() and OnGetMetadata() calls. If you want
|
||||
// to differentiate the protos during the runtime before the start of the
|
||||
// program, use this functor to get its name. We either way need it for
|
||||
// LITE_RUNTIME protos as they don't have descriptors at all.
|
||||
explicit NoOpAccessListener(StringPiece (*name_extractor)()) {}
|
||||
// called repeatedly during serialization/deserialization/ByteSize of
|
||||
// Reflection as:
|
||||
// AccessListener<MessageT>::OnSerialize(this);
|
||||
static void OnSerialize(const MessageLite* msg) {}
|
||||
static void OnDeserialize(const MessageLite* msg) {}
|
||||
static void OnByteSize(const MessageLite* msg) {}
|
||||
static void OnMergeFrom(const MessageLite* to, const MessageLite* from) {}
|
||||
|
||||
// NOTE: This function can be called pre-main. Make sure it does not make
|
||||
// the state of the listener invalid.
|
||||
static void OnGetMetadata() {}
|
||||
|
||||
// called from accessors as:
|
||||
// AccessListener<MessageT>::On$operation(this, &field_storage_);
|
||||
// If you need to override this with type, in your hook implementation
|
||||
// introduce
|
||||
// template <int kFieldNum, typename T>
|
||||
// static void On$operation(const MessageLite* msg,
|
||||
// const T* field) {}
|
||||
// And overloads for std::nullptr_t for incomplete types such as Messages,
|
||||
// Maps. Extract them using reflection if you need. Consequently, second
|
||||
// argument can be null pointer.
|
||||
// For an example, see proto_hooks/testing/memory_test_field_listener.h
|
||||
// And argument template deduction will deduce the type itself without
|
||||
// changing the generated code.
|
||||
|
||||
// add_<field>(f)
|
||||
template <int kFieldNum>
|
||||
static void OnAdd(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// add_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnAddMutable(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// <field>() and <repeated_field>(i)
|
||||
template <int kFieldNum>
|
||||
static void OnGet(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// clear_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnClear(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// has_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnHas(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// <repeated_field>()
|
||||
template <int kFieldNum>
|
||||
static void OnList(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// mutable_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnMutable(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// mutable_<repeated_field>()
|
||||
template <int kFieldNum>
|
||||
static void OnMutableList(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// release_<field>()
|
||||
template <int kFieldNum>
|
||||
static void OnRelease(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// set_<field>() and set_<repeated_field>(i)
|
||||
template <int kFieldNum>
|
||||
static void OnSet(const MessageLite* msg, const void* field) {}
|
||||
|
||||
// <repeated_field>_size()
|
||||
template <int kFieldNum>
|
||||
static void OnSize(const MessageLite* msg, const void* field) {}
|
||||
|
||||
static void OnHasExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
// TODO(b/190614678): Support clear in the proto compiler.
|
||||
static void OnClearExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnExtensionSize(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnGetExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnMutableExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnSetExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnReleaseExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnAddExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnAddMutableExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnListExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
static void OnMutableListExtension(const MessageLite* msg, int extension_tag,
|
||||
const void* field) {}
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#ifndef REPLACE_PROTO_LISTENER_IMPL
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template <class T>
|
||||
using AccessListener = NoOpAccessListener<T>;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#else
|
||||
// You can put your implementations of hooks/listeners here.
|
||||
// All hooks are subject to approval by protobuf-team@.
|
||||
|
||||
#endif // !REPLACE_PROTO_LISTENER_IMPL
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
|
||||
@@ -1,373 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/field_mask.proto
|
||||
|
||||
#include <google/protobuf/field_mask.pb.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// This is a temporary google only hack
|
||||
#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
|
||||
#include "third_party/protobuf/version.h"
|
||||
#endif
|
||||
// @@protoc_insertion_point(includes)
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class FieldMaskDefaultTypeInternal {
|
||||
public:
|
||||
::google::protobuf::internal::ExplicitlyConstructed<FieldMask>
|
||||
_instance;
|
||||
} _FieldMask_default_instance_;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace protobuf_google_2fprotobuf_2ffield_5fmask_2eproto {
|
||||
void InitDefaultsFieldMaskImpl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
|
||||
::google::protobuf::internal::InitProtobufDefaultsForceUnique();
|
||||
#else
|
||||
::google::protobuf::internal::InitProtobufDefaults();
|
||||
#endif // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
|
||||
{
|
||||
void* ptr = &::google::protobuf::_FieldMask_default_instance_;
|
||||
new (ptr) ::google::protobuf::FieldMask();
|
||||
::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
|
||||
}
|
||||
::google::protobuf::FieldMask::InitAsDefaultInstance();
|
||||
}
|
||||
|
||||
void InitDefaultsFieldMask() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &InitDefaultsFieldMaskImpl);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata file_level_metadata[1];
|
||||
|
||||
const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
~0u, // no _has_bits_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::FieldMask, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::FieldMask, paths_),
|
||||
};
|
||||
static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ 0, -1, sizeof(::google::protobuf::FieldMask)},
|
||||
};
|
||||
|
||||
static ::google::protobuf::Message const * const file_default_instances[] = {
|
||||
reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::_FieldMask_default_instance_),
|
||||
};
|
||||
|
||||
void protobuf_AssignDescriptors() {
|
||||
AddDescriptors();
|
||||
::google::protobuf::MessageFactory* factory = NULL;
|
||||
AssignDescriptors(
|
||||
"google/protobuf/field_mask.proto", schemas, file_default_instances, TableStruct::offsets, factory,
|
||||
file_level_metadata, NULL, NULL);
|
||||
}
|
||||
|
||||
void protobuf_AssignDescriptorsOnce() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
|
||||
}
|
||||
|
||||
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD;
|
||||
void protobuf_RegisterTypes(const ::std::string&) {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1);
|
||||
}
|
||||
|
||||
void AddDescriptorsImpl() {
|
||||
InitDefaults();
|
||||
static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
|
||||
"\n google/protobuf/field_mask.proto\022\017goog"
|
||||
"le.protobuf\"\032\n\tFieldMask\022\r\n\005paths\030\001 \003(\tB"
|
||||
"\211\001\n\023com.google.protobufB\016FieldMaskProtoP"
|
||||
"\001Z9google.golang.org/genproto/protobuf/f"
|
||||
"ield_mask;field_mask\242\002\003GPB\252\002\036Google.Prot"
|
||||
"obuf.WellKnownTypesb\006proto3"
|
||||
};
|
||||
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
|
||||
descriptor, 227);
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
||||
"google/protobuf/field_mask.proto", &protobuf_RegisterTypes);
|
||||
}
|
||||
|
||||
void AddDescriptors() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
|
||||
}
|
||||
// Force AddDescriptors() to be called at dynamic initialization time.
|
||||
struct StaticDescriptorInitializer {
|
||||
StaticDescriptorInitializer() {
|
||||
AddDescriptors();
|
||||
}
|
||||
} static_descriptor_initializer;
|
||||
} // namespace protobuf_google_2fprotobuf_2ffield_5fmask_2eproto
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
void FieldMask::InitAsDefaultInstance() {
|
||||
}
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
const int FieldMask::kPathsFieldNumber;
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
|
||||
FieldMask::FieldMask()
|
||||
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
|
||||
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
|
||||
::protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::InitDefaultsFieldMask();
|
||||
}
|
||||
SharedCtor();
|
||||
// @@protoc_insertion_point(constructor:google.protobuf.FieldMask)
|
||||
}
|
||||
FieldMask::FieldMask(const FieldMask& from)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(NULL),
|
||||
paths_(from.paths_),
|
||||
_cached_size_(0) {
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
// @@protoc_insertion_point(copy_constructor:google.protobuf.FieldMask)
|
||||
}
|
||||
|
||||
void FieldMask::SharedCtor() {
|
||||
_cached_size_ = 0;
|
||||
}
|
||||
|
||||
FieldMask::~FieldMask() {
|
||||
// @@protoc_insertion_point(destructor:google.protobuf.FieldMask)
|
||||
SharedDtor();
|
||||
}
|
||||
|
||||
void FieldMask::SharedDtor() {
|
||||
}
|
||||
|
||||
void FieldMask::SetCachedSize(int size) const {
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
}
|
||||
const ::google::protobuf::Descriptor* FieldMask::descriptor() {
|
||||
::protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return ::protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
|
||||
}
|
||||
|
||||
const FieldMask& FieldMask::default_instance() {
|
||||
::protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::InitDefaultsFieldMask();
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
FieldMask* FieldMask::New(::google::protobuf::Arena* arena) const {
|
||||
FieldMask* n = new FieldMask;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void FieldMask::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.FieldMask)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
paths_.Clear();
|
||||
_internal_metadata_.Clear();
|
||||
}
|
||||
|
||||
bool FieldMask::MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) {
|
||||
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
|
||||
::google::protobuf::uint32 tag;
|
||||
// @@protoc_insertion_point(parse_start:google.protobuf.FieldMask)
|
||||
for (;;) {
|
||||
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
|
||||
tag = p.first;
|
||||
if (!p.second) goto handle_unusual;
|
||||
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
|
||||
// repeated string paths = 1;
|
||||
case 1: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
|
||||
input, this->add_paths()));
|
||||
DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->paths(this->paths_size() - 1).data(),
|
||||
static_cast<int>(this->paths(this->paths_size() - 1).length()),
|
||||
::google::protobuf::internal::WireFormatLite::PARSE,
|
||||
"google.protobuf.FieldMask.paths"));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
handle_unusual:
|
||||
if (tag == 0) {
|
||||
goto success;
|
||||
}
|
||||
DO_(::google::protobuf::internal::WireFormat::SkipField(
|
||||
input, tag, _internal_metadata_.mutable_unknown_fields()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success:
|
||||
// @@protoc_insertion_point(parse_success:google.protobuf.FieldMask)
|
||||
return true;
|
||||
failure:
|
||||
// @@protoc_insertion_point(parse_failure:google.protobuf.FieldMask)
|
||||
return false;
|
||||
#undef DO_
|
||||
}
|
||||
|
||||
void FieldMask::SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const {
|
||||
// @@protoc_insertion_point(serialize_start:google.protobuf.FieldMask)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// repeated string paths = 1;
|
||||
for (int i = 0, n = this->paths_size(); i < n; i++) {
|
||||
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->paths(i).data(), static_cast<int>(this->paths(i).length()),
|
||||
::google::protobuf::internal::WireFormatLite::SERIALIZE,
|
||||
"google.protobuf.FieldMask.paths");
|
||||
::google::protobuf::internal::WireFormatLite::WriteString(
|
||||
1, this->paths(i), output);
|
||||
}
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_end:google.protobuf.FieldMask)
|
||||
}
|
||||
|
||||
::google::protobuf::uint8* FieldMask::InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const {
|
||||
(void)deterministic; // Unused
|
||||
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldMask)
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// repeated string paths = 1;
|
||||
for (int i = 0, n = this->paths_size(); i < n; i++) {
|
||||
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->paths(i).data(), static_cast<int>(this->paths(i).length()),
|
||||
::google::protobuf::internal::WireFormatLite::SERIALIZE,
|
||||
"google.protobuf.FieldMask.paths");
|
||||
target = ::google::protobuf::internal::WireFormatLite::
|
||||
WriteStringToArray(1, this->paths(i), target);
|
||||
}
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldMask)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t FieldMask::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldMask)
|
||||
size_t total_size = 0;
|
||||
|
||||
if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
|
||||
total_size +=
|
||||
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
|
||||
(::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()));
|
||||
}
|
||||
// repeated string paths = 1;
|
||||
total_size += 1 *
|
||||
::google::protobuf::internal::FromIntSize(this->paths_size());
|
||||
for (int i = 0, n = this->paths_size(); i < n; i++) {
|
||||
total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
|
||||
this->paths(i));
|
||||
}
|
||||
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = cached_size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void FieldMask::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldMask)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
const FieldMask* source =
|
||||
::google::protobuf::internal::DynamicCastToGenerated<const FieldMask>(
|
||||
&from);
|
||||
if (source == NULL) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldMask)
|
||||
::google::protobuf::internal::ReflectionOps::Merge(from, this);
|
||||
} else {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldMask)
|
||||
MergeFrom(*source);
|
||||
}
|
||||
}
|
||||
|
||||
void FieldMask::MergeFrom(const FieldMask& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldMask)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
::google::protobuf::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
paths_.MergeFrom(from.paths_);
|
||||
}
|
||||
|
||||
void FieldMask::CopyFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldMask)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
void FieldMask::CopyFrom(const FieldMask& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FieldMask)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool FieldMask::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void FieldMask::Swap(FieldMask* other) {
|
||||
if (other == this) return;
|
||||
InternalSwap(other);
|
||||
}
|
||||
void FieldMask::InternalSwap(FieldMask* other) {
|
||||
using std::swap;
|
||||
paths_.InternalSwap(&other->paths_);
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
swap(_cached_size_, other->_cached_size_);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata FieldMask::GetMetadata() const {
|
||||
protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return ::protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::file_level_metadata[kIndexInFileMessages];
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
+171
-114
@@ -1,177 +1,228 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/field_mask.proto
|
||||
|
||||
#ifndef PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED
|
||||
#define PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3005000
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3019000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3005001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
|
||||
#if 3019001 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_table_driven.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ffield_5fmask_2eproto PROTOBUF_EXPORT
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
namespace protobuf_google_2fprotobuf_2ffield_5fmask_2eproto {
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct LIBPROTOBUF_EXPORT TableStruct {
|
||||
static const ::google::protobuf::internal::ParseTableField entries[];
|
||||
static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
|
||||
static const ::google::protobuf::internal::ParseTable schema[1];
|
||||
static const ::google::protobuf::internal::FieldMetadata field_metadata[];
|
||||
static const ::google::protobuf::internal::SerializationTable serialization_table[];
|
||||
static const ::google::protobuf::uint32 offsets[];
|
||||
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto {
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[];
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
|
||||
static const uint32_t offsets[];
|
||||
};
|
||||
void LIBPROTOBUF_EXPORT AddDescriptors();
|
||||
void LIBPROTOBUF_EXPORT InitDefaultsFieldMaskImpl();
|
||||
void LIBPROTOBUF_EXPORT InitDefaultsFieldMask();
|
||||
inline void LIBPROTOBUF_EXPORT InitDefaults() {
|
||||
InitDefaultsFieldMask();
|
||||
}
|
||||
} // namespace protobuf_google_2fprotobuf_2ffield_5fmask_2eproto
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto;
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
class FieldMask;
|
||||
class FieldMaskDefaultTypeInternal;
|
||||
LIBPROTOBUF_EXPORT extern FieldMaskDefaultTypeInternal _FieldMask_default_instance_;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
struct FieldMaskDefaultTypeInternal;
|
||||
PROTOBUF_EXPORT extern FieldMaskDefaultTypeInternal _FieldMask_default_instance_;
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FieldMask* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FieldMask>(Arena*);
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class LIBPROTOBUF_EXPORT FieldMask : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldMask) */ {
|
||||
class PROTOBUF_EXPORT FieldMask final :
|
||||
public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldMask) */ {
|
||||
public:
|
||||
FieldMask();
|
||||
virtual ~FieldMask();
|
||||
inline FieldMask() : FieldMask(nullptr) {}
|
||||
~FieldMask() override;
|
||||
explicit constexpr FieldMask(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
|
||||
|
||||
FieldMask(const FieldMask& from);
|
||||
|
||||
inline FieldMask& operator=(const FieldMask& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
#if LANG_CXX11
|
||||
FieldMask(FieldMask&& from) noexcept
|
||||
: FieldMask() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline FieldMask& operator=(const FieldMask& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline FieldMask& operator=(FieldMask&& from) noexcept {
|
||||
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
|
||||
if (this != &from) InternalSwap(&from);
|
||||
if (this == &from) return *this;
|
||||
if (GetOwningArena() == from.GetOwningArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetOwningArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const FieldMask& default_instance();
|
||||
|
||||
static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const FieldMask& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const FieldMask* internal_default_instance() {
|
||||
return reinterpret_cast<const FieldMask*>(
|
||||
&_FieldMask_default_instance_);
|
||||
}
|
||||
static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
void Swap(FieldMask* other);
|
||||
friend void swap(FieldMask& a, FieldMask& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(FieldMask* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() != nullptr &&
|
||||
GetOwningArena() == other->GetOwningArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() == other->GetOwningArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(FieldMask* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline FieldMask* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
|
||||
FieldMask* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
FieldMask* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
|
||||
return CreateMaybeMessage<FieldMask>(arena);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
|
||||
void CopyFrom(const FieldMask& from);
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
|
||||
void MergeFrom(const FieldMask& from);
|
||||
void Clear() PROTOBUF_FINAL;
|
||||
bool IsInitialized() const PROTOBUF_FINAL;
|
||||
private:
|
||||
static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from);
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
|
||||
uint8_t* _InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
|
||||
int GetCachedSize() const final { return _cached_size_.Get(); }
|
||||
|
||||
size_t ByteSizeLong() const PROTOBUF_FINAL;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
|
||||
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const PROTOBUF_FINAL;
|
||||
void SetCachedSize(int size) const final;
|
||||
void InternalSwap(FieldMask* other);
|
||||
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return NULL;
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return NULL;
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "google.protobuf.FieldMask";
|
||||
}
|
||||
protected:
|
||||
explicit FieldMask(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned = false);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
|
||||
static const ClassData _class_data_;
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
enum : int {
|
||||
kPathsFieldNumber = 1,
|
||||
};
|
||||
// repeated string paths = 1;
|
||||
int paths_size() const;
|
||||
private:
|
||||
int _internal_paths_size() const;
|
||||
public:
|
||||
void clear_paths();
|
||||
static const int kPathsFieldNumber = 1;
|
||||
const ::std::string& paths(int index) const;
|
||||
::std::string* mutable_paths(int index);
|
||||
void set_paths(int index, const ::std::string& value);
|
||||
#if LANG_CXX11
|
||||
void set_paths(int index, ::std::string&& value);
|
||||
#endif
|
||||
const std::string& paths(int index) const;
|
||||
std::string* mutable_paths(int index);
|
||||
void set_paths(int index, const std::string& value);
|
||||
void set_paths(int index, std::string&& value);
|
||||
void set_paths(int index, const char* value);
|
||||
void set_paths(int index, const char* value, size_t size);
|
||||
::std::string* add_paths();
|
||||
void add_paths(const ::std::string& value);
|
||||
#if LANG_CXX11
|
||||
void add_paths(::std::string&& value);
|
||||
#endif
|
||||
std::string* add_paths();
|
||||
void add_paths(const std::string& value);
|
||||
void add_paths(std::string&& value);
|
||||
void add_paths(const char* value);
|
||||
void add_paths(const char* value, size_t size);
|
||||
const ::google::protobuf::RepeatedPtrField< ::std::string>& paths() const;
|
||||
::google::protobuf::RepeatedPtrField< ::std::string>* mutable_paths();
|
||||
const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& paths() const;
|
||||
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_paths();
|
||||
private:
|
||||
const std::string& _internal_paths(int index) const;
|
||||
std::string* _internal_add_paths();
|
||||
public:
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.FieldMask)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
::google::protobuf::RepeatedPtrField< ::std::string> paths_;
|
||||
mutable int _cached_size_;
|
||||
friend struct ::protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::TableStruct;
|
||||
friend void ::protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::InitDefaultsFieldMaskImpl();
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string> paths_;
|
||||
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
|
||||
friend struct ::TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
@@ -185,32 +236,41 @@ class LIBPROTOBUF_EXPORT FieldMask : public ::google::protobuf::Message /* @@pro
|
||||
// FieldMask
|
||||
|
||||
// repeated string paths = 1;
|
||||
inline int FieldMask::paths_size() const {
|
||||
inline int FieldMask::_internal_paths_size() const {
|
||||
return paths_.size();
|
||||
}
|
||||
inline int FieldMask::paths_size() const {
|
||||
return _internal_paths_size();
|
||||
}
|
||||
inline void FieldMask::clear_paths() {
|
||||
paths_.Clear();
|
||||
}
|
||||
inline const ::std::string& FieldMask::paths(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.FieldMask.paths)
|
||||
inline std::string* FieldMask::add_paths() {
|
||||
std::string* _s = _internal_add_paths();
|
||||
// @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths)
|
||||
return _s;
|
||||
}
|
||||
inline const std::string& FieldMask::_internal_paths(int index) const {
|
||||
return paths_.Get(index);
|
||||
}
|
||||
inline ::std::string* FieldMask::mutable_paths(int index) {
|
||||
inline const std::string& FieldMask::paths(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.FieldMask.paths)
|
||||
return _internal_paths(index);
|
||||
}
|
||||
inline std::string* FieldMask::mutable_paths(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.FieldMask.paths)
|
||||
return paths_.Mutable(index);
|
||||
}
|
||||
inline void FieldMask::set_paths(int index, const ::std::string& value) {
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
|
||||
inline void FieldMask::set_paths(int index, const std::string& value) {
|
||||
paths_.Mutable(index)->assign(value);
|
||||
}
|
||||
#if LANG_CXX11
|
||||
inline void FieldMask::set_paths(int index, ::std::string&& value) {
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
|
||||
paths_.Mutable(index)->assign(std::move(value));
|
||||
}
|
||||
#endif
|
||||
inline void FieldMask::set_paths(int index, std::string&& value) {
|
||||
paths_.Mutable(index)->assign(std::move(value));
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline void FieldMask::set_paths(int index, const char* value) {
|
||||
GOOGLE_DCHECK(value != NULL);
|
||||
GOOGLE_DCHECK(value != nullptr);
|
||||
paths_.Mutable(index)->assign(value);
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
@@ -219,22 +279,19 @@ inline void FieldMask::set_paths(int index, const char* value, size_t size) {
|
||||
reinterpret_cast<const char*>(value), size);
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline ::std::string* FieldMask::add_paths() {
|
||||
// @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths)
|
||||
inline std::string* FieldMask::_internal_add_paths() {
|
||||
return paths_.Add();
|
||||
}
|
||||
inline void FieldMask::add_paths(const ::std::string& value) {
|
||||
inline void FieldMask::add_paths(const std::string& value) {
|
||||
paths_.Add()->assign(value);
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
inline void FieldMask::add_paths(::std::string&& value) {
|
||||
inline void FieldMask::add_paths(std::string&& value) {
|
||||
paths_.Add(std::move(value));
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
#endif
|
||||
inline void FieldMask::add_paths(const char* value) {
|
||||
GOOGLE_DCHECK(value != NULL);
|
||||
GOOGLE_DCHECK(value != nullptr);
|
||||
paths_.Add()->assign(value);
|
||||
// @@protoc_insertion_point(field_add_char:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
@@ -242,12 +299,12 @@ inline void FieldMask::add_paths(const char* value, size_t size) {
|
||||
paths_.Add()->assign(reinterpret_cast<const char*>(value), size);
|
||||
// @@protoc_insertion_point(field_add_pointer:google.protobuf.FieldMask.paths)
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
|
||||
inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>&
|
||||
FieldMask::paths() const {
|
||||
// @@protoc_insertion_point(field_list:google.protobuf.FieldMask.paths)
|
||||
return paths_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::std::string>*
|
||||
inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>*
|
||||
FieldMask::mutable_paths() {
|
||||
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldMask.paths)
|
||||
return &paths_;
|
||||
@@ -259,9 +316,9 @@ FieldMask::mutable_paths() {
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto
|
||||
|
||||
@@ -41,14 +41,23 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/template_util.h>
|
||||
#include <google/protobuf/generated_enum_util.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class EnumDescriptor;
|
||||
class EnumDescriptor;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Returns the EnumDescriptor for enum type E, which must be a
|
||||
@@ -59,16 +68,14 @@ const EnumDescriptor* GetEnumDescriptor();
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Helper for EnumType_Parse functions: try to parse the string 'name' as an
|
||||
// enum name of the given type, returning true and filling in value on success,
|
||||
// or returning false and leaving value unchanged on failure.
|
||||
LIBPROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor,
|
||||
const string& name,
|
||||
int* value);
|
||||
// Helper for EnumType_Parse functions: try to parse the string 'name' as
|
||||
// an enum name of the given type, returning true and filling in value on
|
||||
// success, or returning false and leaving value unchanged on failure.
|
||||
PROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor,
|
||||
ConstStringParam name, int* value);
|
||||
|
||||
template<typename EnumType>
|
||||
bool ParseNamedEnum(const EnumDescriptor* descriptor,
|
||||
const string& name,
|
||||
template <typename EnumType>
|
||||
bool ParseNamedEnum(const EnumDescriptor* descriptor, ConstStringParam name,
|
||||
EnumType* value) {
|
||||
int tmp;
|
||||
if (!ParseNamedEnum(descriptor, name, &tmp)) return false;
|
||||
@@ -79,10 +86,13 @@ bool ParseNamedEnum(const EnumDescriptor* descriptor,
|
||||
// Just a wrapper around printing the name of a value. The main point of this
|
||||
// function is not to be inlined, so that you can do this without including
|
||||
// descriptor.h.
|
||||
LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value);
|
||||
PROTOBUF_EXPORT const std::string& NameOfEnum(const EnumDescriptor* descriptor,
|
||||
int value);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
|
||||
|
||||
+40
-3
@@ -31,16 +31,53 @@
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
|
||||
|
||||
#include <google/protobuf/stubs/template_util.h>
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// This type trait can be used to cause templates to only match proto2 enum
|
||||
// types.
|
||||
template <typename T> struct is_proto_enum : ::google::protobuf::internal::false_type {};
|
||||
template <typename T>
|
||||
struct is_proto_enum : ::std::false_type {};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// The table entry format for storing enum name-to-value mapping used with lite
|
||||
// protos. This struct and the following related functions should only be used
|
||||
// by protobuf generated code.
|
||||
struct EnumEntry {
|
||||
StringPiece name;
|
||||
int value;
|
||||
};
|
||||
|
||||
// Looks up a numeric enum value given the string name.
|
||||
PROTOBUF_EXPORT bool LookUpEnumValue(const EnumEntry* enums, size_t size,
|
||||
StringPiece name, int* value);
|
||||
|
||||
// Looks up an enum name given the numeric value.
|
||||
PROTOBUF_EXPORT int LookUpEnumName(const EnumEntry* enums,
|
||||
const int* sorted_indices, size_t size,
|
||||
int value);
|
||||
|
||||
// Initializes the list of enum names in std::string form.
|
||||
PROTOBUF_EXPORT bool InitializeEnumStrings(
|
||||
const EnumEntry* enums, const int* sorted_indices, size_t size,
|
||||
internal::ExplicitlyConstructed<std::string>* enum_strings);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file contains helpers for generated code.
|
||||
//
|
||||
// Nothing in this file should be directly referenced by users of protobufs.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__
|
||||
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/message.h>
|
||||
|
||||
// Must come last:
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// To save code size, protos without any fields are derived from ZeroFieldsBase
|
||||
// rather than Message.
|
||||
class PROTOBUF_EXPORT ZeroFieldsBase : public Message {
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final { return true; }
|
||||
size_t ByteSizeLong() const final;
|
||||
int GetCachedSize() const final { return _cached_size_.Get(); }
|
||||
const char* _InternalParse(const char* ptr,
|
||||
internal::ParseContext* ctx) final;
|
||||
::uint8_t* _InternalSerialize(::uint8_t* target,
|
||||
io::EpsCopyOutputStream* stream) const final;
|
||||
|
||||
protected:
|
||||
constexpr ZeroFieldsBase() {}
|
||||
explicit ZeroFieldsBase(Arena* arena, bool is_message_owned)
|
||||
: Message(arena, is_message_owned) {}
|
||||
ZeroFieldsBase(const ZeroFieldsBase&) = delete;
|
||||
ZeroFieldsBase& operator=(const ZeroFieldsBase&) = delete;
|
||||
~ZeroFieldsBase() override;
|
||||
|
||||
void SetCachedSize(int size) const final { _cached_size_.Set(size); }
|
||||
|
||||
static void MergeImpl(Message* to, const Message& from);
|
||||
static void CopyImpl(Message* to, const Message& from);
|
||||
void InternalSwap(ZeroFieldsBase* other);
|
||||
|
||||
mutable internal::CachedSize _cached_size_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__
|
||||
+1782
-1126
File diff suppressed because it is too large
Load Diff
+172
-538
@@ -42,45 +42,36 @@
|
||||
#include <vector>
|
||||
#include <google/protobuf/stubs/casts.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
// TODO(jasonh): Remove this once the compiler change to directly include this
|
||||
// is released to components.
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_enum_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/metadata.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace upb {
|
||||
namespace google_opensource {
|
||||
class GMR_Handlers;
|
||||
} // namespace google_opensource
|
||||
} // namespace upb
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class DescriptorPool;
|
||||
class MapKey;
|
||||
class MapValueRef;
|
||||
class MessageLayoutInspector;
|
||||
class Message;
|
||||
struct Metadata;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
|
||||
namespace protobuf {
|
||||
namespace flat {
|
||||
class MetadataBuilder;
|
||||
} // namespace flat
|
||||
} // namespace protobuf
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
class DefaultEmptyOneof;
|
||||
|
||||
// Defined in this file.
|
||||
class GeneratedMessageReflection;
|
||||
|
||||
// Defined in other files.
|
||||
class ExtensionSet; // extension_set.h
|
||||
class WeakFieldMap; // weak_field_map.h
|
||||
class ExtensionSet; // extension_set.h
|
||||
class WeakFieldMap; // weak_field_map.h
|
||||
|
||||
// This struct describes the internal layout of the message, hence this is
|
||||
// used to act on the message reflectively.
|
||||
@@ -88,17 +79,17 @@ class WeakFieldMap; // weak_field_map.h
|
||||
// used to obtain pointers to default instances of embedded
|
||||
// messages, which GetMessage() will return if the particular
|
||||
// sub-message has not been initialized yet. (Thus, all
|
||||
// embedded message fields *must* have non-NULL pointers
|
||||
// embedded message fields *must* have non-null pointers
|
||||
// in the default instance.)
|
||||
// offsets: An array of ints giving the byte offsets.
|
||||
// For each oneof or weak field, the offset is relative to the
|
||||
// default_instance. These can be computed at compile time
|
||||
// using the
|
||||
// GOOGLE_PROTOBUF_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET()
|
||||
// PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET()
|
||||
// macro. For each none oneof field, the offset is related to
|
||||
// the start of the message object. These can be computed at
|
||||
// compile time using the
|
||||
// GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET() macro.
|
||||
// PROTO2_GENERATED_MESSAGE_FIELD_OFFSET() macro.
|
||||
// Besides offsets for all fields, this array also contains
|
||||
// offsets for oneof unions. The offset of the i-th oneof union
|
||||
// is offsets[descriptor->field_count() + i].
|
||||
@@ -116,7 +107,7 @@ class WeakFieldMap; // weak_field_map.h
|
||||
// message, or -1 if the message type has no extension
|
||||
// ranges.
|
||||
// oneof_case_offset: Offset in the message of an array of uint32s of
|
||||
// size descriptor->oneof_decl_count(). Each uint32
|
||||
// size descriptor->oneof_decl_count(). Each uint32_t
|
||||
// indicates what field is set for each oneof.
|
||||
// object_size: The size of a message object of this type, as measured
|
||||
// by sizeof().
|
||||
@@ -128,62 +119,88 @@ class WeakFieldMap; // weak_field_map.h
|
||||
struct ReflectionSchema {
|
||||
public:
|
||||
// Size of a google::protobuf::Message object of this type.
|
||||
uint32 GetObjectSize() const { return static_cast<uint32>(object_size_); }
|
||||
uint32_t GetObjectSize() const { return static_cast<uint32_t>(object_size_); }
|
||||
|
||||
bool InRealOneof(const FieldDescriptor* field) const {
|
||||
return field->containing_oneof() &&
|
||||
!field->containing_oneof()->is_synthetic();
|
||||
}
|
||||
|
||||
// Offset of a non-oneof field. Getting a field offset is slightly more
|
||||
// efficient when we know statically that it is not a oneof field.
|
||||
uint32 GetFieldOffsetNonOneof(const FieldDescriptor* field) const {
|
||||
GOOGLE_DCHECK(!field->containing_oneof());
|
||||
return offsets_[field->index()];
|
||||
uint32_t GetFieldOffsetNonOneof(const FieldDescriptor* field) const {
|
||||
GOOGLE_DCHECK(!InRealOneof(field));
|
||||
return OffsetValue(offsets_[field->index()], field->type());
|
||||
}
|
||||
|
||||
// Offset of any field.
|
||||
uint32 GetFieldOffset(const FieldDescriptor* field) const {
|
||||
if (field->containing_oneof()) {
|
||||
uint32_t GetFieldOffset(const FieldDescriptor* field) const {
|
||||
if (InRealOneof(field)) {
|
||||
size_t offset =
|
||||
static_cast<size_t>(field->containing_type()->field_count() +
|
||||
field->containing_oneof()->index());
|
||||
return offsets_[offset];
|
||||
field->containing_oneof()->index());
|
||||
return OffsetValue(offsets_[offset], field->type());
|
||||
} else {
|
||||
return GetFieldOffsetNonOneof(field);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetOneofCaseOffset(const OneofDescriptor* oneof_descriptor) const {
|
||||
return static_cast<uint32>(oneof_case_offset_) +
|
||||
static_cast<uint32>(
|
||||
static_cast<size_t>(oneof_descriptor->index()) * sizeof(uint32));
|
||||
bool IsFieldInlined(const FieldDescriptor* field) const {
|
||||
return Inlined(offsets_[field->index()], field->type());
|
||||
}
|
||||
|
||||
uint32_t GetOneofCaseOffset(const OneofDescriptor* oneof_descriptor) const {
|
||||
return static_cast<uint32_t>(oneof_case_offset_) +
|
||||
static_cast<uint32_t>(
|
||||
static_cast<size_t>(oneof_descriptor->index()) *
|
||||
sizeof(uint32_t));
|
||||
}
|
||||
|
||||
bool HasHasbits() const { return has_bits_offset_ != -1; }
|
||||
|
||||
// Bit index within the bit array of hasbits. Bit order is low-to-high.
|
||||
uint32 HasBitIndex(const FieldDescriptor* field) const {
|
||||
uint32_t HasBitIndex(const FieldDescriptor* field) const {
|
||||
if (has_bits_offset_ == -1) return static_cast<uint32_t>(-1);
|
||||
GOOGLE_DCHECK(HasHasbits());
|
||||
return has_bit_indices_[field->index()];
|
||||
}
|
||||
|
||||
// Byte offset of the hasbits array.
|
||||
uint32 HasBitsOffset() const {
|
||||
uint32_t HasBitsOffset() const {
|
||||
GOOGLE_DCHECK(HasHasbits());
|
||||
return static_cast<uint32>(has_bits_offset_);
|
||||
return static_cast<uint32_t>(has_bits_offset_);
|
||||
}
|
||||
|
||||
bool HasInlinedString() const { return inlined_string_donated_offset_ != -1; }
|
||||
|
||||
// Bit index within the bit array of _inlined_string_donated_. Bit order is
|
||||
// low-to-high.
|
||||
uint32_t InlinedStringIndex(const FieldDescriptor* field) const {
|
||||
GOOGLE_DCHECK(HasInlinedString());
|
||||
return inlined_string_indices_[field->index()];
|
||||
}
|
||||
|
||||
// Byte offset of the _inlined_string_donated_ array.
|
||||
uint32_t InlinedStringDonatedOffset() const {
|
||||
GOOGLE_DCHECK(HasInlinedString());
|
||||
return static_cast<uint32_t>(inlined_string_donated_offset_);
|
||||
}
|
||||
|
||||
// The offset of the InternalMetadataWithArena member.
|
||||
// For Lite this will actually be an InternalMetadataWithArenaLite.
|
||||
// The schema doesn't contain enough information to distinguish between
|
||||
// these two cases.
|
||||
uint32 GetMetadataOffset() const {
|
||||
return static_cast<uint32>(metadata_offset_);
|
||||
uint32_t GetMetadataOffset() const {
|
||||
return static_cast<uint32_t>(metadata_offset_);
|
||||
}
|
||||
|
||||
// Whether this message has an ExtensionSet.
|
||||
bool HasExtensionSet() const { return extensions_offset_ != -1; }
|
||||
|
||||
// The offset of the ExtensionSet in this message.
|
||||
uint32 GetExtensionSetOffset() const {
|
||||
uint32_t GetExtensionSetOffset() const {
|
||||
GOOGLE_DCHECK(HasExtensionSet());
|
||||
return static_cast<uint32>(extensions_offset_);
|
||||
return static_cast<uint32_t>(extensions_offset_);
|
||||
}
|
||||
|
||||
// The off set of WeakFieldMap when the message contains weak fields.
|
||||
@@ -196,9 +213,33 @@ struct ReflectionSchema {
|
||||
|
||||
// Returns a pointer to the default value for this field. The size and type
|
||||
// of the underlying data depends on the field's type.
|
||||
const void *GetFieldDefault(const FieldDescriptor* field) const {
|
||||
return reinterpret_cast<const uint8*>(default_instance_) +
|
||||
offsets_[field->index()];
|
||||
const void* GetFieldDefault(const FieldDescriptor* field) const {
|
||||
return reinterpret_cast<const uint8_t*>(default_instance_) +
|
||||
OffsetValue(offsets_[field->index()], field->type());
|
||||
}
|
||||
|
||||
// Returns true if the field is implicitly backed by LazyField.
|
||||
bool IsEagerlyVerifiedLazyField(const FieldDescriptor* field) const {
|
||||
GOOGLE_DCHECK_EQ(field->type(), FieldDescriptor::TYPE_MESSAGE);
|
||||
(void)field;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns true if the field's accessor is called by any external code (aka,
|
||||
// non proto library code).
|
||||
bool IsFieldUsed(const FieldDescriptor* field) const {
|
||||
(void)field;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsFieldStripped(const FieldDescriptor* field) const {
|
||||
(void)field;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsMessageStripped(const Descriptor* descriptor) const {
|
||||
(void)descriptor;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -209,16 +250,39 @@ struct ReflectionSchema {
|
||||
// them, ie.
|
||||
//
|
||||
// ReflectionSchema schema = {a, b, c, d, e, ...};
|
||||
// private:
|
||||
// private:
|
||||
const Message* default_instance_;
|
||||
const uint32* offsets_;
|
||||
const uint32* has_bit_indices_;
|
||||
const uint32_t* offsets_;
|
||||
const uint32_t* has_bit_indices_;
|
||||
int has_bits_offset_;
|
||||
int metadata_offset_;
|
||||
int extensions_offset_;
|
||||
int oneof_case_offset_;
|
||||
int object_size_;
|
||||
int weak_field_map_offset_;
|
||||
const uint32_t* inlined_string_indices_;
|
||||
int inlined_string_donated_offset_;
|
||||
|
||||
// We tag offset values to provide additional data about fields (such as
|
||||
// "unused" or "lazy" or "inlined").
|
||||
static uint32_t OffsetValue(uint32_t v, FieldDescriptor::Type type) {
|
||||
if (type == FieldDescriptor::TYPE_MESSAGE ||
|
||||
type == FieldDescriptor::TYPE_STRING ||
|
||||
type == FieldDescriptor::TYPE_BYTES) {
|
||||
return v & 0x7FFFFFFEu;
|
||||
}
|
||||
return v & 0x7FFFFFFFu;
|
||||
}
|
||||
|
||||
static bool Inlined(uint32_t v, FieldDescriptor::Type type) {
|
||||
if (type == FieldDescriptor::TYPE_STRING ||
|
||||
type == FieldDescriptor::TYPE_BYTES) {
|
||||
return (v & 1u) != 0u;
|
||||
} else {
|
||||
// Non string/byte fields are not inlined.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Structs that the code generator emits directly to describe a message.
|
||||
@@ -228,501 +292,71 @@ struct ReflectionSchema {
|
||||
// EXPERIMENTAL: these are changing rapidly, and may completely disappear
|
||||
// or merge with ReflectionSchema.
|
||||
struct MigrationSchema {
|
||||
int32 offsets_index;
|
||||
int32 has_bit_indices_index;
|
||||
int32_t offsets_index;
|
||||
int32_t has_bit_indices_index;
|
||||
int32_t inlined_string_indices_index;
|
||||
int object_size;
|
||||
};
|
||||
|
||||
// THIS CLASS IS NOT INTENDED FOR DIRECT USE. It is intended for use
|
||||
// by generated code. This class is just a big hack that reduces code
|
||||
// size.
|
||||
//
|
||||
// A GeneratedMessageReflection is an implementation of Reflection
|
||||
// which expects all fields to be backed by simple variables located in
|
||||
// memory. The locations are given using a base pointer and a set of
|
||||
// offsets.
|
||||
//
|
||||
// It is required that the user represents fields of each type in a standard
|
||||
// way, so that GeneratedMessageReflection can cast the void* pointer to
|
||||
// the appropriate type. For primitive fields and string fields, each field
|
||||
// should be represented using the obvious C++ primitive type. Enums and
|
||||
// Messages are different:
|
||||
// - Singular Message fields are stored as a pointer to a Message. These
|
||||
// should start out NULL, except for in the default instance where they
|
||||
// should start out pointing to other default instances.
|
||||
// - Enum fields are stored as an int. This int must always contain
|
||||
// a valid value, such that EnumDescriptor::FindValueByNumber() would
|
||||
// not return NULL.
|
||||
// - Repeated fields are stored as RepeatedFields or RepeatedPtrFields
|
||||
// of whatever type the individual field would be. Strings and
|
||||
// Messages use RepeatedPtrFields while everything else uses
|
||||
// RepeatedFields.
|
||||
class LIBPROTOBUF_EXPORT GeneratedMessageReflection PROTOBUF_FINAL : public Reflection {
|
||||
public:
|
||||
// Constructs a GeneratedMessageReflection.
|
||||
// Parameters:
|
||||
// descriptor: The descriptor for the message type being implemented.
|
||||
// schema: The description of the internal guts of the message.
|
||||
// pool: DescriptorPool to search for extension definitions. Only
|
||||
// used by FindKnownExtensionByName() and
|
||||
// FindKnownExtensionByNumber().
|
||||
// factory: MessageFactory to use to construct extension messages.
|
||||
GeneratedMessageReflection(const Descriptor* descriptor,
|
||||
const ReflectionSchema& schema,
|
||||
const DescriptorPool* pool,
|
||||
MessageFactory* factory);
|
||||
|
||||
~GeneratedMessageReflection();
|
||||
|
||||
// implements Reflection -------------------------------------------
|
||||
|
||||
const UnknownFieldSet& GetUnknownFields(const Message& message) const;
|
||||
UnknownFieldSet* MutableUnknownFields(Message* message) const;
|
||||
|
||||
size_t SpaceUsedLong(const Message& message) const;
|
||||
|
||||
bool HasField(const Message& message, const FieldDescriptor* field) const;
|
||||
int FieldSize(const Message& message, const FieldDescriptor* field) const;
|
||||
void ClearField(Message* message, const FieldDescriptor* field) const;
|
||||
bool HasOneof(const Message& message,
|
||||
const OneofDescriptor* oneof_descriptor) const;
|
||||
void ClearOneof(Message* message, const OneofDescriptor* field) const;
|
||||
void RemoveLast(Message* message, const FieldDescriptor* field) const;
|
||||
Message* ReleaseLast(Message* message, const FieldDescriptor* field) const;
|
||||
void Swap(Message* message1, Message* message2) const;
|
||||
void SwapFields(Message* message1, Message* message2,
|
||||
const std::vector<const FieldDescriptor*>& fields) const;
|
||||
void SwapElements(Message* message, const FieldDescriptor* field,
|
||||
int index1, int index2) const;
|
||||
void ListFields(const Message& message,
|
||||
std::vector<const FieldDescriptor*>* output) const;
|
||||
|
||||
int32 GetInt32 (const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
int64 GetInt64 (const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
uint32 GetUInt32(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
uint64 GetUInt64(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
float GetFloat (const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
double GetDouble(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
bool GetBool (const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
string GetString(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
const string& GetStringReference(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
string* scratch) const;
|
||||
const EnumValueDescriptor* GetEnum(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
int GetEnumValue(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
const Message& GetMessage(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
MessageFactory* factory = NULL) const;
|
||||
|
||||
const FieldDescriptor* GetOneofFieldDescriptor(
|
||||
const Message& message,
|
||||
const OneofDescriptor* oneof_descriptor) const;
|
||||
|
||||
private:
|
||||
bool ContainsMapKey(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
const MapKey& key) const;
|
||||
bool InsertOrLookupMapValue(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
const MapKey& key,
|
||||
MapValueRef* val) const;
|
||||
bool DeleteMapValue(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
const MapKey& key) const;
|
||||
MapIterator MapBegin(
|
||||
Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
MapIterator MapEnd(
|
||||
Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
int MapSize(const Message& message, const FieldDescriptor* field) const;
|
||||
|
||||
public:
|
||||
void SetInt32 (Message* message,
|
||||
const FieldDescriptor* field, int32 value) const;
|
||||
void SetInt64 (Message* message,
|
||||
const FieldDescriptor* field, int64 value) const;
|
||||
void SetUInt32(Message* message,
|
||||
const FieldDescriptor* field, uint32 value) const;
|
||||
void SetUInt64(Message* message,
|
||||
const FieldDescriptor* field, uint64 value) const;
|
||||
void SetFloat (Message* message,
|
||||
const FieldDescriptor* field, float value) const;
|
||||
void SetDouble(Message* message,
|
||||
const FieldDescriptor* field, double value) const;
|
||||
void SetBool (Message* message,
|
||||
const FieldDescriptor* field, bool value) const;
|
||||
void SetString(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
const string& value) const;
|
||||
void SetEnum (Message* message, const FieldDescriptor* field,
|
||||
const EnumValueDescriptor* value) const;
|
||||
void SetEnumValue(Message* message, const FieldDescriptor* field,
|
||||
int value) const;
|
||||
Message* MutableMessage(Message* message, const FieldDescriptor* field,
|
||||
MessageFactory* factory = NULL) const;
|
||||
void SetAllocatedMessage(Message* message,
|
||||
Message* sub_message,
|
||||
const FieldDescriptor* field) const;
|
||||
Message* ReleaseMessage(Message* message, const FieldDescriptor* field,
|
||||
MessageFactory* factory = NULL) const;
|
||||
|
||||
int32 GetRepeatedInt32 (const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
int64 GetRepeatedInt64 (const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
uint32 GetRepeatedUInt32(const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
uint64 GetRepeatedUInt64(const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
float GetRepeatedFloat (const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
double GetRepeatedDouble(const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
bool GetRepeatedBool (const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
string GetRepeatedString(const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
const string& GetRepeatedStringReference(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index, string* scratch) const;
|
||||
const EnumValueDescriptor* GetRepeatedEnum(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
int GetRepeatedEnumValue(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
const Message& GetRepeatedMessage(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
|
||||
// Set the value of a field.
|
||||
void SetRepeatedInt32 (Message* message,
|
||||
const FieldDescriptor* field, int index, int32 value) const;
|
||||
void SetRepeatedInt64 (Message* message,
|
||||
const FieldDescriptor* field, int index, int64 value) const;
|
||||
void SetRepeatedUInt32(Message* message,
|
||||
const FieldDescriptor* field, int index, uint32 value) const;
|
||||
void SetRepeatedUInt64(Message* message,
|
||||
const FieldDescriptor* field, int index, uint64 value) const;
|
||||
void SetRepeatedFloat (Message* message,
|
||||
const FieldDescriptor* field, int index, float value) const;
|
||||
void SetRepeatedDouble(Message* message,
|
||||
const FieldDescriptor* field, int index, double value) const;
|
||||
void SetRepeatedBool (Message* message,
|
||||
const FieldDescriptor* field, int index, bool value) const;
|
||||
void SetRepeatedString(Message* message,
|
||||
const FieldDescriptor* field, int index,
|
||||
const string& value) const;
|
||||
void SetRepeatedEnum(Message* message, const FieldDescriptor* field,
|
||||
int index, const EnumValueDescriptor* value) const;
|
||||
void SetRepeatedEnumValue(Message* message, const FieldDescriptor* field,
|
||||
int index, int value) const;
|
||||
// Get a mutable pointer to a field with a message type.
|
||||
Message* MutableRepeatedMessage(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
|
||||
void AddInt32 (Message* message,
|
||||
const FieldDescriptor* field, int32 value) const;
|
||||
void AddInt64 (Message* message,
|
||||
const FieldDescriptor* field, int64 value) const;
|
||||
void AddUInt32(Message* message,
|
||||
const FieldDescriptor* field, uint32 value) const;
|
||||
void AddUInt64(Message* message,
|
||||
const FieldDescriptor* field, uint64 value) const;
|
||||
void AddFloat (Message* message,
|
||||
const FieldDescriptor* field, float value) const;
|
||||
void AddDouble(Message* message,
|
||||
const FieldDescriptor* field, double value) const;
|
||||
void AddBool (Message* message,
|
||||
const FieldDescriptor* field, bool value) const;
|
||||
void AddString(Message* message,
|
||||
const FieldDescriptor* field, const string& value) const;
|
||||
void AddEnum(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
const EnumValueDescriptor* value) const;
|
||||
void AddEnumValue(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int value) const;
|
||||
Message* AddMessage(Message* message, const FieldDescriptor* field,
|
||||
MessageFactory* factory = NULL) const;
|
||||
void AddAllocatedMessage(
|
||||
Message* message, const FieldDescriptor* field,
|
||||
Message* new_entry) const;
|
||||
|
||||
const FieldDescriptor* FindKnownExtensionByName(const string& name) const;
|
||||
const FieldDescriptor* FindKnownExtensionByNumber(int number) const;
|
||||
|
||||
bool SupportsUnknownEnumValues() const;
|
||||
|
||||
// This value for arena_offset_ indicates that there is no arena pointer in
|
||||
// this message (e.g., old generated code).
|
||||
static const int kNoArenaPointer = -1;
|
||||
|
||||
// This value for unknown_field_offset_ indicates that there is no
|
||||
// UnknownFieldSet in this message, and that instead, we are using the
|
||||
// Zero-Overhead Arena Pointer trick. When this is the case, arena_offset_
|
||||
// actually indexes to an InternalMetadataWithArena instance, which can return
|
||||
// either an arena pointer or an UnknownFieldSet or both. It is never the case
|
||||
// that unknown_field_offset_ == kUnknownFieldSetInMetadata && arena_offset_
|
||||
// == kNoArenaPointer.
|
||||
static const int kUnknownFieldSetInMetadata = -1;
|
||||
|
||||
protected:
|
||||
void* MutableRawRepeatedField(
|
||||
Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
|
||||
int ctype, const Descriptor* desc) const;
|
||||
|
||||
const void* GetRawRepeatedField(
|
||||
const Message& message, const FieldDescriptor* field,
|
||||
FieldDescriptor::CppType, int ctype,
|
||||
const Descriptor* desc) const;
|
||||
|
||||
virtual MessageFactory* GetMessageFactory() const;
|
||||
|
||||
virtual void* RepeatedFieldData(
|
||||
Message* message, const FieldDescriptor* field,
|
||||
FieldDescriptor::CppType cpp_type,
|
||||
const Descriptor* message_type) const;
|
||||
|
||||
private:
|
||||
friend class google::protobuf::flat::MetadataBuilder;
|
||||
friend class upb::google_opensource::GMR_Handlers;
|
||||
|
||||
const Descriptor* const descriptor_;
|
||||
const ReflectionSchema schema_;
|
||||
const DescriptorPool* const descriptor_pool_;
|
||||
MessageFactory* const message_factory_;
|
||||
|
||||
// Last non weak field index. This is an optimization when most weak fields
|
||||
// are at the end of the containing message. If a message proto doesn't
|
||||
// contain weak fields, then this field equals descriptor_->field_count().
|
||||
int last_non_weak_field_index_;
|
||||
|
||||
template <class T>
|
||||
const T& GetRawNonOneof(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
template <class T>
|
||||
T* MutableRawNonOneof(Message* message, const FieldDescriptor* field) const;
|
||||
|
||||
template <typename Type>
|
||||
const Type& GetRaw(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
template <typename Type>
|
||||
inline Type* MutableRaw(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
template <typename Type>
|
||||
inline const Type& DefaultRaw(const FieldDescriptor* field) const;
|
||||
|
||||
inline const uint32* GetHasBits(const Message& message) const;
|
||||
inline uint32* MutableHasBits(Message* message) const;
|
||||
inline uint32 GetOneofCase(
|
||||
const Message& message,
|
||||
const OneofDescriptor* oneof_descriptor) const;
|
||||
inline uint32* MutableOneofCase(
|
||||
Message* message,
|
||||
const OneofDescriptor* oneof_descriptor) const;
|
||||
inline const ExtensionSet& GetExtensionSet(const Message& message) const;
|
||||
inline ExtensionSet* MutableExtensionSet(Message* message) const;
|
||||
inline Arena* GetArena(Message* message) const;
|
||||
|
||||
inline const InternalMetadataWithArena& GetInternalMetadataWithArena(
|
||||
const Message& message) const;
|
||||
|
||||
inline InternalMetadataWithArena*
|
||||
MutableInternalMetadataWithArena(Message* message) const;
|
||||
|
||||
inline bool HasBit(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
inline void SetBit(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
inline void ClearBit(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
inline void SwapBit(Message* message1,
|
||||
Message* message2,
|
||||
const FieldDescriptor* field) const;
|
||||
|
||||
// This function only swaps the field. Should swap corresponding has_bit
|
||||
// before or after using this function.
|
||||
void SwapField(Message* message1,
|
||||
Message* message2,
|
||||
const FieldDescriptor* field) const;
|
||||
|
||||
void SwapOneofField(Message* message1,
|
||||
Message* message2,
|
||||
const OneofDescriptor* oneof_descriptor) const;
|
||||
|
||||
inline bool HasOneofField(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
inline void SetOneofCase(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
inline void ClearOneofField(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
|
||||
template <typename Type>
|
||||
inline const Type& GetField(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
template <typename Type>
|
||||
inline void SetField(Message* message,
|
||||
const FieldDescriptor* field, const Type& value) const;
|
||||
template <typename Type>
|
||||
inline Type* MutableField(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
template <typename Type>
|
||||
inline const Type& GetRepeatedField(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
template <typename Type>
|
||||
inline const Type& GetRepeatedPtrField(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
template <typename Type>
|
||||
inline void SetRepeatedField(Message* message,
|
||||
const FieldDescriptor* field, int index,
|
||||
Type value) const;
|
||||
template <typename Type>
|
||||
inline Type* MutableRepeatedField(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
template <typename Type>
|
||||
inline void AddField(Message* message,
|
||||
const FieldDescriptor* field, const Type& value) const;
|
||||
template <typename Type>
|
||||
inline Type* AddField(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
|
||||
int GetExtensionNumberOrDie(const Descriptor* type) const;
|
||||
|
||||
// Internal versions of EnumValue API perform no checking. Called after checks
|
||||
// by public methods.
|
||||
void SetEnumValueInternal(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int value) const;
|
||||
void SetRepeatedEnumValueInternal(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index,
|
||||
int value) const;
|
||||
void AddEnumValueInternal(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int value) const;
|
||||
|
||||
|
||||
Message* UnsafeArenaReleaseMessage(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
MessageFactory* factory = NULL) const;
|
||||
|
||||
void UnsafeArenaSetAllocatedMessage(Message* message,
|
||||
Message* sub_message,
|
||||
const FieldDescriptor* field) const;
|
||||
|
||||
internal::MapFieldBase* MapData(
|
||||
Message* message, const FieldDescriptor* field) const;
|
||||
|
||||
friend inline // inline so nobody can call this function.
|
||||
void
|
||||
RegisterAllTypesInternal(const Metadata* file_level_metadata, int size);
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratedMessageReflection);
|
||||
// This struct tries to reduce unnecessary padding.
|
||||
// The num_xxx might not be close to their respective pointer, but this saves
|
||||
// padding.
|
||||
struct PROTOBUF_EXPORT DescriptorTable {
|
||||
mutable bool is_initialized;
|
||||
bool is_eager;
|
||||
int size; // of serialized descriptor
|
||||
const char* descriptor;
|
||||
const char* filename;
|
||||
once_flag* once;
|
||||
const DescriptorTable* const* deps;
|
||||
int num_deps;
|
||||
int num_messages;
|
||||
const MigrationSchema* schemas;
|
||||
const Message* const* default_instances;
|
||||
const uint32_t* offsets;
|
||||
// update the following descriptor arrays.
|
||||
Metadata* file_level_metadata;
|
||||
const EnumDescriptor** file_level_enum_descriptors;
|
||||
const ServiceDescriptor** file_level_service_descriptors;
|
||||
};
|
||||
|
||||
// There are some places in proto2 where dynamic_cast would be useful as an
|
||||
// optimization. For example, take Message::MergeFrom(const Message& other).
|
||||
// For a given generated message FooMessage, we generate these two methods:
|
||||
// void MergeFrom(const FooMessage& other);
|
||||
// void MergeFrom(const Message& other);
|
||||
// The former method can be implemented directly in terms of FooMessage's
|
||||
// inline accessors, but the latter method must work with the reflection
|
||||
// interface. However, if the parameter to the latter method is actually of
|
||||
// type FooMessage, then we'd like to be able to just call the other method
|
||||
// as an optimization. So, we use dynamic_cast to check this.
|
||||
//
|
||||
// That said, dynamic_cast requires RTTI, which many people like to disable
|
||||
// for performance and code size reasons. When RTTI is not available, we
|
||||
// still need to produce correct results. So, in this case we have to fall
|
||||
// back to using reflection, which is what we would have done anyway if the
|
||||
// objects were not of the exact same class.
|
||||
//
|
||||
// dynamic_cast_if_available() implements this logic. If RTTI is
|
||||
// enabled, it does a dynamic_cast. If RTTI is disabled, it just returns
|
||||
// NULL.
|
||||
//
|
||||
// If you need to compile without RTTI, simply #define GOOGLE_PROTOBUF_NO_RTTI.
|
||||
// On MSVC, this should be detected automatically.
|
||||
template<typename To, typename From>
|
||||
inline To dynamic_cast_if_available(From from) {
|
||||
#if defined(GOOGLE_PROTOBUF_NO_RTTI) || (defined(_MSC_VER)&&!defined(_CPPRTTI))
|
||||
// Avoid the compiler warning about unused variables.
|
||||
(void)from;
|
||||
return NULL;
|
||||
#else
|
||||
return dynamic_cast<To>(from);
|
||||
#endif
|
||||
}
|
||||
enum {
|
||||
// Tag used on offsets for fields that don't have a real offset.
|
||||
// For example, weak message fields go into the WeakFieldMap and not in an
|
||||
// actual field.
|
||||
kInvalidFieldOffsetTag = 0x40000000u,
|
||||
};
|
||||
|
||||
// Tries to downcast this message to a generated message type.
|
||||
// Returns NULL if this class is not an instance of T.
|
||||
//
|
||||
// This is like dynamic_cast_if_available, except it works even when
|
||||
// dynamic_cast is not available by using Reflection. However it only works
|
||||
// with Message objects.
|
||||
//
|
||||
// TODO(haberman): can we remove dynamic_cast_if_available in favor of this?
|
||||
template <typename T>
|
||||
T* DynamicCastToGenerated(const Message* from) {
|
||||
// Compile-time assert that T is a generated type that has a
|
||||
// default_instance() accessor, but avoid actually calling it.
|
||||
const T&(*get_default_instance)() = &T::default_instance;
|
||||
(void)get_default_instance;
|
||||
// AssignDescriptors() pulls the compiled FileDescriptor from the DescriptorPool
|
||||
// and uses it to populate all of the global variables which store pointers to
|
||||
// the descriptor objects. It also constructs the reflection objects. It is
|
||||
// called the first time anyone calls descriptor() or GetReflection() on one of
|
||||
// the types defined in the file. AssignDescriptors() is thread-safe.
|
||||
void PROTOBUF_EXPORT AssignDescriptors(const DescriptorTable* table,
|
||||
bool eager = false);
|
||||
|
||||
// Compile-time assert that T is a subclass of google::protobuf::Message.
|
||||
const Message* unused = static_cast<T*>(NULL);
|
||||
(void)unused;
|
||||
|
||||
#if defined(GOOGLE_PROTOBUF_NO_RTTI) || \
|
||||
(defined(_MSC_VER) && !defined(_CPPRTTI))
|
||||
bool ok = &T::default_instance() ==
|
||||
from->GetReflection()->GetMessageFactory()->GetPrototype(
|
||||
from->GetDescriptor());
|
||||
return ok ? down_cast<T*>(from) : NULL;
|
||||
#else
|
||||
return dynamic_cast<T*>(from);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* DynamicCastToGenerated(Message* from) {
|
||||
const Message* message_const = from;
|
||||
return const_cast<T*>(DynamicCastToGenerated<const T>(message_const));
|
||||
}
|
||||
|
||||
LIBPROTOBUF_EXPORT void AssignDescriptors(
|
||||
const string& filename, const MigrationSchema* schemas,
|
||||
const Message* const* default_instances_, const uint32* offsets,
|
||||
MessageFactory* factory,
|
||||
// update the following descriptor arrays.
|
||||
Metadata* file_level_metadata,
|
||||
const EnumDescriptor** file_level_enum_descriptors,
|
||||
const ServiceDescriptor** file_level_service_descriptors);
|
||||
|
||||
LIBPROTOBUF_EXPORT void RegisterAllTypes(const Metadata* file_level_metadata, int size);
|
||||
// Overload used to implement GetMetadataStatic in the generated code.
|
||||
// See comments in compiler/cpp/internal/file.cc as to why.
|
||||
// It takes a `Metadata` and returns it to allow for tail calls and reduce
|
||||
// binary size.
|
||||
Metadata PROTOBUF_EXPORT AssignDescriptors(const DescriptorTable* (*table)(),
|
||||
internal::once_flag* once,
|
||||
const Metadata& metadata);
|
||||
|
||||
// These cannot be in lite so we put them in the reflection.
|
||||
LIBPROTOBUF_EXPORT void UnknownFieldSetSerializer(const uint8* base, uint32 offset, uint32 tag,
|
||||
uint32 has_offset,
|
||||
::google::protobuf::io::CodedOutputStream* output);
|
||||
PROTOBUF_EXPORT void UnknownFieldSetSerializer(const uint8_t* base,
|
||||
uint32_t offset, uint32_t tag,
|
||||
uint32_t has_offset,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
struct PROTOBUF_EXPORT AddDescriptorsRunner {
|
||||
explicit AddDescriptorsRunner(const DescriptorTable* table);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/generated_message_table_driven.h>
|
||||
|
||||
#include <google/protobuf/stubs/type_traits.h>
|
||||
|
||||
#include <google/protobuf/generated_message_table_driven_lite.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/metadata.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
namespace {
|
||||
|
||||
UnknownFieldSet* MutableUnknownFields(MessageLite* msg, int64 arena_offset) {
|
||||
return Raw<InternalMetadataWithArena>(msg, arena_offset)
|
||||
->mutable_unknown_fields();
|
||||
}
|
||||
|
||||
struct UnknownFieldHandler {
|
||||
static bool Skip(MessageLite* msg, const ParseTable& table,
|
||||
io::CodedInputStream* input,
|
||||
int tag) {
|
||||
GOOGLE_DCHECK(table.unknown_field_set);
|
||||
|
||||
return WireFormat::SkipField(input, tag,
|
||||
MutableUnknownFields(msg, table.arena_offset));
|
||||
}
|
||||
|
||||
static void Varint(MessageLite* msg, const ParseTable& table,
|
||||
int tag, int value) {
|
||||
GOOGLE_DCHECK(table.unknown_field_set);
|
||||
|
||||
MutableUnknownFields(msg, table.arena_offset)->AddVarint(
|
||||
WireFormatLite::GetTagFieldNumber(tag), value);
|
||||
}
|
||||
|
||||
static bool ParseExtension(
|
||||
MessageLite* msg, const ParseTable& table,
|
||||
io::CodedInputStream* input, int tag) {
|
||||
ExtensionSet* extensions = GetExtensionSet(msg, table.extension_offset);
|
||||
if (extensions == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Message* prototype = down_cast<const Message*>(
|
||||
table.default_instance());
|
||||
|
||||
GOOGLE_DCHECK(prototype != NULL);
|
||||
GOOGLE_DCHECK(table.unknown_field_set);
|
||||
UnknownFieldSet* unknown_fields =
|
||||
MutableUnknownFields(msg, table.arena_offset);
|
||||
|
||||
return extensions->ParseField(tag, input, prototype, unknown_fields);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
bool MergePartialFromCodedStream(
|
||||
MessageLite* msg, const ParseTable& table, io::CodedInputStream* input) {
|
||||
return MergePartialFromCodedStreamImpl<UnknownFieldHandler,
|
||||
InternalMetadataWithArena>(msg, table,
|
||||
input);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -36,10 +36,6 @@
|
||||
#include <google/protobuf/map_field_lite.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
|
||||
#if LANG_CXX11
|
||||
#define PROTOBUF_CONSTEXPR constexpr
|
||||
|
||||
// We require C++11 and Clang to use constexpr for variables, as GCC 4.8
|
||||
// requires constexpr to be consistent between declarations of variables
|
||||
@@ -51,37 +47,72 @@
|
||||
#define PROTOBUF_CONSTEXPR_VAR
|
||||
#endif // !_clang
|
||||
|
||||
#else
|
||||
#define PROTOBUF_CONSTEXPR
|
||||
#define PROTOBUF_CONSTEXPR_VAR
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Processing-type masks.
|
||||
static PROTOBUF_CONSTEXPR const unsigned char kOneofMask = 0x40;
|
||||
static PROTOBUF_CONSTEXPR const unsigned char kRepeatedMask = 0x20;
|
||||
static constexpr const unsigned char kOneofMask = 0x40;
|
||||
static constexpr const unsigned char kRepeatedMask = 0x20;
|
||||
// Mask for the raw type: either a WireFormatLite::FieldType or one of the
|
||||
// ProcessingTypes below, without the oneof or repeated flag.
|
||||
static PROTOBUF_CONSTEXPR const unsigned char kTypeMask = 0x1f;
|
||||
static constexpr const unsigned char kTypeMask = 0x1f;
|
||||
|
||||
// Wire type masks.
|
||||
static PROTOBUF_CONSTEXPR const unsigned char kNotPackedMask = 0x10;
|
||||
static PROTOBUF_CONSTEXPR const unsigned char kInvalidMask = 0x20;
|
||||
static constexpr const unsigned char kNotPackedMask = 0x10;
|
||||
static constexpr const unsigned char kInvalidMask = 0x20;
|
||||
|
||||
enum ProcessingTypes {
|
||||
TYPE_STRING_CORD = 19,
|
||||
TYPE_STRING_STRING_PIECE = 20,
|
||||
TYPE_BYTES_CORD = 21,
|
||||
TYPE_BYTES_STRING_PIECE = 22,
|
||||
TYPE_MAP = 23,
|
||||
TYPE_STRING_INLINED = 23,
|
||||
TYPE_BYTES_INLINED = 24,
|
||||
TYPE_MAP = 25,
|
||||
};
|
||||
|
||||
#if LANG_CXX11
|
||||
static_assert(TYPE_MAP < kRepeatedMask, "Invalid enum");
|
||||
#endif
|
||||
|
||||
struct PROTOBUF_EXPORT FieldMetadata {
|
||||
uint32_t offset; // offset of this field in the struct
|
||||
uint32_t tag; // field * 8 + wire_type
|
||||
// byte offset * 8 + bit_offset;
|
||||
// if the high bit is set then this is the byte offset of the oneof_case
|
||||
// for this field.
|
||||
uint32_t has_offset;
|
||||
uint32_t type; // the type of this field.
|
||||
const void* ptr; // auxiliary data
|
||||
|
||||
// From the serializer point of view each fundamental type can occur in
|
||||
// 4 different ways. For simplicity we treat all combinations as a cartesion
|
||||
// product although not all combinations are allowed.
|
||||
enum FieldTypeClass {
|
||||
kPresence,
|
||||
kNoPresence,
|
||||
kRepeated,
|
||||
kPacked,
|
||||
kOneOf,
|
||||
kNumTypeClasses // must be last enum
|
||||
};
|
||||
// C++ protobuf has 20 fundamental types, were we added Cord and StringPiece
|
||||
// and also distinguish the same types if they have different wire format.
|
||||
enum {
|
||||
kCordType = 19,
|
||||
kStringPieceType = 20,
|
||||
kInlinedType = 21,
|
||||
kNumTypes = 21,
|
||||
kSpecial = kNumTypes * kNumTypeClasses,
|
||||
};
|
||||
|
||||
static int CalculateType(int fundamental_type, FieldTypeClass type_class);
|
||||
};
|
||||
|
||||
// TODO(ckennelly): Add a static assertion to ensure that these masks do not
|
||||
// conflict with wiretypes.
|
||||
@@ -89,12 +120,12 @@ static_assert(TYPE_MAP < kRepeatedMask, "Invalid enum");
|
||||
// ParseTableField is kept small to help simplify instructions for computing
|
||||
// offsets, as we will always need this information to parse a field.
|
||||
// Additional data, needed for some types, is stored in
|
||||
// AuxillaryParseTableField.
|
||||
// AuxiliaryParseTableField.
|
||||
struct ParseTableField {
|
||||
uint32 offset;
|
||||
uint32_t offset;
|
||||
// The presence_index ordinarily represents a has_bit index, but for fields
|
||||
// inside a oneof it represents the index in _oneof_case_.
|
||||
uint32 presence_index;
|
||||
uint32_t presence_index;
|
||||
unsigned char normal_wiretype;
|
||||
unsigned char packed_wiretype;
|
||||
|
||||
@@ -107,7 +138,7 @@ struct ParseTableField {
|
||||
|
||||
struct ParseTable;
|
||||
|
||||
union AuxillaryParseTableField {
|
||||
union AuxiliaryParseTableField {
|
||||
typedef bool (*EnumValidator)(int);
|
||||
|
||||
// Enums
|
||||
@@ -124,7 +155,6 @@ union AuxillaryParseTableField {
|
||||
const MessageLite* default_message() const {
|
||||
return static_cast<const MessageLite*>(default_message_void);
|
||||
}
|
||||
const ParseTable* parse_table;
|
||||
};
|
||||
message_aux messages;
|
||||
// Strings
|
||||
@@ -139,33 +169,28 @@ union AuxillaryParseTableField {
|
||||
};
|
||||
map_aux maps;
|
||||
|
||||
#if LANG_CXX11
|
||||
AuxillaryParseTableField() = default;
|
||||
#else
|
||||
AuxillaryParseTableField() { }
|
||||
#endif
|
||||
PROTOBUF_CONSTEXPR AuxillaryParseTableField(
|
||||
AuxillaryParseTableField::enum_aux e) : enums(e) {}
|
||||
PROTOBUF_CONSTEXPR AuxillaryParseTableField(
|
||||
AuxillaryParseTableField::message_aux m) : messages(m) {}
|
||||
PROTOBUF_CONSTEXPR AuxillaryParseTableField(
|
||||
AuxillaryParseTableField::string_aux s) : strings(s) {}
|
||||
PROTOBUF_CONSTEXPR AuxillaryParseTableField(
|
||||
AuxillaryParseTableField::map_aux m)
|
||||
AuxiliaryParseTableField() = default;
|
||||
constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::enum_aux e)
|
||||
: enums(e) {}
|
||||
constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::message_aux m)
|
||||
: messages(m) {}
|
||||
constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::string_aux s)
|
||||
: strings(s) {}
|
||||
constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::map_aux m)
|
||||
: maps(m) {}
|
||||
};
|
||||
|
||||
struct ParseTable {
|
||||
const ParseTableField* fields;
|
||||
const AuxillaryParseTableField* aux;
|
||||
const AuxiliaryParseTableField* aux;
|
||||
int max_field_number;
|
||||
// TODO(ckennelly): Do something with this padding.
|
||||
|
||||
// TODO(ckennelly): Vet these for sign extension.
|
||||
int64 has_bits_offset;
|
||||
int64 oneof_case_offset;
|
||||
int64 extension_offset;
|
||||
int64 arena_offset;
|
||||
int64_t has_bits_offset;
|
||||
int64_t oneof_case_offset;
|
||||
int64_t extension_offset;
|
||||
int64_t arena_offset;
|
||||
|
||||
// ExplicitlyInitialized<T> -> T requires a reinterpret_cast, which prevents
|
||||
// the tables from being constructed as a constexpr. We use void to avoid
|
||||
@@ -178,42 +203,149 @@ struct ParseTable {
|
||||
bool unknown_field_set;
|
||||
};
|
||||
|
||||
// TODO(jhen): Remove the __NVCC__ check when we get a version of nvcc that
|
||||
// supports these checks.
|
||||
#if LANG_CXX11 && !defined(__NVCC__)
|
||||
static_assert(sizeof(ParseTableField) <= 16, "ParseTableField is too large");
|
||||
// The tables must be composed of POD components to ensure link-time
|
||||
// initialization.
|
||||
static_assert(std::is_pod<ParseTableField>::value, "");
|
||||
static_assert(std::is_pod<AuxillaryParseTableField>::value, "");
|
||||
static_assert(std::is_pod<AuxillaryParseTableField::enum_aux>::value, "");
|
||||
static_assert(std::is_pod<AuxillaryParseTableField::message_aux>::value, "");
|
||||
static_assert(std::is_pod<AuxillaryParseTableField::string_aux>::value, "");
|
||||
static_assert(std::is_pod<ParseTable>::value, "");
|
||||
#endif
|
||||
static_assert(std::is_standard_layout<ParseTableField>::value, "");
|
||||
static_assert(std::is_trivial<ParseTableField>::value, "");
|
||||
static_assert(std::is_standard_layout<AuxiliaryParseTableField>::value, "");
|
||||
static_assert(std::is_trivial<AuxiliaryParseTableField>::value, "");
|
||||
static_assert(
|
||||
std::is_standard_layout<AuxiliaryParseTableField::enum_aux>::value, "");
|
||||
static_assert(std::is_trivial<AuxiliaryParseTableField::enum_aux>::value, "");
|
||||
static_assert(
|
||||
std::is_standard_layout<AuxiliaryParseTableField::message_aux>::value, "");
|
||||
static_assert(std::is_trivial<AuxiliaryParseTableField::message_aux>::value,
|
||||
"");
|
||||
static_assert(
|
||||
std::is_standard_layout<AuxiliaryParseTableField::string_aux>::value, "");
|
||||
static_assert(std::is_trivial<AuxiliaryParseTableField::string_aux>::value, "");
|
||||
static_assert(std::is_standard_layout<ParseTable>::value, "");
|
||||
static_assert(std::is_trivial<ParseTable>::value, "");
|
||||
|
||||
// TODO(ckennelly): Consolidate these implementations into a single one, using
|
||||
// dynamic dispatch to the appropriate unknown field handler.
|
||||
bool MergePartialFromCodedStream(MessageLite* msg, const ParseTable& table,
|
||||
io::CodedInputStream* input);
|
||||
bool MergePartialFromCodedStreamLite(MessageLite* msg, const ParseTable& table,
|
||||
io::CodedInputStream* input);
|
||||
io::CodedInputStream* input);
|
||||
|
||||
template <typename Entry>
|
||||
bool ParseMap(io::CodedInputStream* input, void* map_field) {
|
||||
typedef typename MapEntryToMapField<Entry>::MapFieldType MapFieldType;
|
||||
typedef google::protobuf::Map<typename Entry::EntryKeyType,
|
||||
typename Entry::EntryValueType>
|
||||
typedef Map<typename Entry::EntryKeyType, typename Entry::EntryValueType>
|
||||
MapType;
|
||||
typedef typename Entry::template Parser<MapFieldType, MapType> ParserType;
|
||||
|
||||
ParserType parser(static_cast<MapFieldType*>(map_field));
|
||||
return ::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(input,
|
||||
&parser);
|
||||
return WireFormatLite::ReadMessageNoVirtual(input, &parser);
|
||||
}
|
||||
|
||||
struct SerializationTable {
|
||||
int num_fields;
|
||||
const FieldMetadata* field_table;
|
||||
};
|
||||
|
||||
PROTOBUF_EXPORT void SerializeInternal(const uint8_t* base,
|
||||
const FieldMetadata* table,
|
||||
int32_t num_fields,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
inline void TableSerialize(const MessageLite& msg,
|
||||
const SerializationTable* table,
|
||||
io::CodedOutputStream* output) {
|
||||
const FieldMetadata* field_table = table->field_table;
|
||||
int num_fields = table->num_fields - 1;
|
||||
const uint8_t* base = reinterpret_cast<const uint8_t*>(&msg);
|
||||
// TODO(gerbens) This skips the first test if we could use the fast
|
||||
// array serialization path, we should make this
|
||||
// int cached_size =
|
||||
// *reinterpret_cast<const int32_t*>(base + field_table->offset);
|
||||
// SerializeWithCachedSize(msg, field_table + 1, num_fields, cached_size, ...)
|
||||
// But we keep conformance with the old way for now.
|
||||
SerializeInternal(base, field_table + 1, num_fields, output);
|
||||
}
|
||||
|
||||
PROTOBUF_EXPORT uint8_t* SerializeInternalToArray(const uint8_t* base,
|
||||
const FieldMetadata* table,
|
||||
int32_t num_fields,
|
||||
bool is_deterministic,
|
||||
uint8_t* buffer);
|
||||
|
||||
inline uint8_t* TableSerializeToArray(const MessageLite& msg,
|
||||
const SerializationTable* table,
|
||||
bool is_deterministic, uint8_t* buffer) {
|
||||
const uint8_t* base = reinterpret_cast<const uint8_t*>(&msg);
|
||||
const FieldMetadata* field_table = table->field_table + 1;
|
||||
int num_fields = table->num_fields - 1;
|
||||
return SerializeInternalToArray(base, field_table, num_fields,
|
||||
is_deterministic, buffer);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct CompareHelper {
|
||||
bool operator()(const T& a, const T& b) const { return a < b; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct CompareHelper<ArenaStringPtr> {
|
||||
bool operator()(const ArenaStringPtr& a, const ArenaStringPtr& b) const {
|
||||
return a.Get() < b.Get();
|
||||
}
|
||||
};
|
||||
|
||||
struct CompareMapKey {
|
||||
template <typename T>
|
||||
bool operator()(const MapEntryHelper<T>& a,
|
||||
const MapEntryHelper<T>& b) const {
|
||||
return Compare(a.key_, b.key_);
|
||||
}
|
||||
template <typename T>
|
||||
bool Compare(const T& a, const T& b) const {
|
||||
return CompareHelper<T>()(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename MapFieldType, const SerializationTable* table>
|
||||
void MapFieldSerializer(const uint8_t* base, uint32_t offset, uint32_t tag,
|
||||
uint32_t has_offset, io::CodedOutputStream* output) {
|
||||
typedef MapEntryHelper<typename MapFieldType::EntryTypeTrait> Entry;
|
||||
typedef typename MapFieldType::MapType::const_iterator Iter;
|
||||
|
||||
const MapFieldType& map_field =
|
||||
*reinterpret_cast<const MapFieldType*>(base + offset);
|
||||
const SerializationTable* t =
|
||||
table +
|
||||
has_offset; // has_offset is overloaded for maps to mean table offset
|
||||
if (!output->IsSerializationDeterministic()) {
|
||||
for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
|
||||
++it) {
|
||||
Entry map_entry(*it);
|
||||
output->WriteVarint32(tag);
|
||||
output->WriteVarint32(map_entry._cached_size_);
|
||||
SerializeInternal(reinterpret_cast<const uint8_t*>(&map_entry),
|
||||
t->field_table, t->num_fields, output);
|
||||
}
|
||||
} else {
|
||||
std::vector<Entry> v;
|
||||
for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
|
||||
++it) {
|
||||
v.push_back(Entry(*it));
|
||||
}
|
||||
std::sort(v.begin(), v.end(), CompareMapKey());
|
||||
for (int i = 0; i < v.size(); i++) {
|
||||
output->WriteVarint32(tag);
|
||||
output->WriteVarint32(v[i]._cached_size_);
|
||||
SerializeInternal(reinterpret_cast<const uint8_t*>(&v[i]), t->field_table,
|
||||
t->num_fields, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_H__
|
||||
|
||||
-109
@@ -1,109 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/generated_message_table_driven_lite.h>
|
||||
|
||||
#include <google/protobuf/stubs/type_traits.h>
|
||||
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
namespace {
|
||||
|
||||
string* MutableUnknownFields(MessageLite* msg, int64 arena_offset) {
|
||||
return Raw<InternalMetadataWithArenaLite>(msg, arena_offset)
|
||||
->mutable_unknown_fields();
|
||||
}
|
||||
|
||||
struct UnknownFieldHandlerLite {
|
||||
static bool Skip(MessageLite* msg, const ParseTable& table,
|
||||
io::CodedInputStream* input,
|
||||
int tag) {
|
||||
GOOGLE_DCHECK(!table.unknown_field_set);
|
||||
::google::protobuf::io::StringOutputStream unknown_fields_string(
|
||||
MutableUnknownFields(msg, table.arena_offset));
|
||||
::google::protobuf::io::CodedOutputStream unknown_fields_stream(
|
||||
&unknown_fields_string, false);
|
||||
|
||||
return ::google::protobuf::internal::WireFormatLite::SkipField(
|
||||
input, tag, &unknown_fields_stream);
|
||||
}
|
||||
|
||||
static void Varint(MessageLite* msg, const ParseTable& table,
|
||||
int tag, int value) {
|
||||
GOOGLE_DCHECK(!table.unknown_field_set);
|
||||
|
||||
::google::protobuf::io::StringOutputStream unknown_fields_string(
|
||||
MutableUnknownFields(msg, table.arena_offset));
|
||||
::google::protobuf::io::CodedOutputStream unknown_fields_stream(
|
||||
&unknown_fields_string, false);
|
||||
unknown_fields_stream.WriteVarint32(tag);
|
||||
unknown_fields_stream.WriteVarint32(value);
|
||||
}
|
||||
|
||||
static bool ParseExtension(
|
||||
MessageLite* msg, const ParseTable& table,
|
||||
io::CodedInputStream* input, int tag) {
|
||||
ExtensionSet* extensions = GetExtensionSet(msg, table.extension_offset);
|
||||
if (extensions == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const MessageLite* prototype = table.default_instance();
|
||||
|
||||
GOOGLE_DCHECK(!table.unknown_field_set);
|
||||
::google::protobuf::io::StringOutputStream unknown_fields_string(
|
||||
MutableUnknownFields(msg, table.arena_offset));
|
||||
::google::protobuf::io::CodedOutputStream unknown_fields_stream(
|
||||
&unknown_fields_string, false);
|
||||
return extensions->ParseField(
|
||||
tag, input, prototype, &unknown_fields_stream);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
bool MergePartialFromCodedStreamLite(
|
||||
MessageLite* msg, const ParseTable& table, io::CodedInputStream* input) {
|
||||
return MergePartialFromCodedStreamImpl<UnknownFieldHandlerLite,
|
||||
InternalMetadataWithArenaLite>(
|
||||
msg, table, input);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -1,823 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_LITE_H__
|
||||
|
||||
#include <google/protobuf/generated_message_table_driven.h>
|
||||
|
||||
#include <google/protobuf/stubs/type_traits.h>
|
||||
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
|
||||
enum StringType {
|
||||
StringType_STRING = 0,
|
||||
StringType_CORD = 1,
|
||||
StringType_STRING_PIECE = 2
|
||||
};
|
||||
|
||||
// Logically a superset of StringType, consisting of all field types that
|
||||
// require special initialization.
|
||||
enum ProcessingType {
|
||||
ProcessingType_STRING = 0,
|
||||
ProcessingType_CORD = 1,
|
||||
ProcessingType_STRING_PIECE = 2,
|
||||
ProcessingType_MESSAGE = 3
|
||||
};
|
||||
|
||||
enum Cardinality {
|
||||
Cardinality_SINGULAR = 0,
|
||||
Cardinality_REPEATED = 1,
|
||||
Cardinality_ONEOF = 3
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
inline Type* Raw(MessageLite* msg, int64 offset) {
|
||||
return reinterpret_cast<Type*>(reinterpret_cast<uint8*>(msg) + offset);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline const Type* Raw(const MessageLite* msg, int64 offset) {
|
||||
return reinterpret_cast<const Type*>(reinterpret_cast<const uint8*>(msg) +
|
||||
offset);
|
||||
}
|
||||
|
||||
template <typename InternalMetadata>
|
||||
inline Arena* GetArena(MessageLite* msg, int64 arena_offset) {
|
||||
if (GOOGLE_PREDICT_FALSE(arena_offset == -1)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Raw<InternalMetadata>(msg, arena_offset)->arena();
|
||||
}
|
||||
|
||||
inline ExtensionSet* GetExtensionSet(MessageLite* msg, int64 extension_offset) {
|
||||
if (extension_offset == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Raw<ExtensionSet>(msg, extension_offset);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type* AddField(MessageLite* msg, int64 offset) {
|
||||
#if LANG_CXX11
|
||||
static_assert(has_trivial_copy<Type>::value,
|
||||
"Do not assign");
|
||||
#endif
|
||||
|
||||
google::protobuf::RepeatedField<Type>* repeated =
|
||||
Raw<google::protobuf::RepeatedField<Type> >(msg, offset);
|
||||
return repeated->Add();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline string* AddField<string>(MessageLite* msg, int64 offset) {
|
||||
google::protobuf::RepeatedPtrField<string>* repeated =
|
||||
Raw<google::protobuf::RepeatedPtrField<string> >(msg, offset);
|
||||
return repeated->Add();
|
||||
}
|
||||
|
||||
|
||||
template <typename Type>
|
||||
inline void AddField(MessageLite* msg, int64 offset, Type value) {
|
||||
#if LANG_CXX11
|
||||
static_assert(has_trivial_copy<Type>::value,
|
||||
"Do not assign");
|
||||
#endif
|
||||
*AddField<Type>(msg, offset) = value;
|
||||
}
|
||||
|
||||
inline void SetBit(uint32* has_bits, uint32 has_bit_index) {
|
||||
GOOGLE_DCHECK(has_bits != NULL);
|
||||
|
||||
uint32 mask = static_cast<uint32>(1u) << (has_bit_index % 32);
|
||||
has_bits[has_bit_index / 32u] |= mask;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type* MutableField(MessageLite* msg, uint32* has_bits,
|
||||
uint32 has_bit_index, int64 offset) {
|
||||
SetBit(has_bits, has_bit_index);
|
||||
return Raw<Type>(msg, offset);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline void SetField(MessageLite* msg, uint32* has_bits, uint32 has_bit_index,
|
||||
int64 offset, Type value) {
|
||||
#if LANG_CXX11
|
||||
static_assert(has_trivial_copy<Type>::value,
|
||||
"Do not assign");
|
||||
#endif
|
||||
*MutableField<Type>(msg, has_bits, has_bit_index, offset) = value;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline void SetOneofField(MessageLite* msg, uint32* oneof_case,
|
||||
uint32 oneof_case_index, int64 offset,
|
||||
int field_number, Type value) {
|
||||
oneof_case[oneof_case_index] = field_number;
|
||||
*Raw<Type>(msg, offset) = value;
|
||||
}
|
||||
|
||||
// Clears a oneof field. The field argument should correspond to the particular
|
||||
// field that is currently set in the oneof.
|
||||
inline void ClearOneofField(const ParseTableField& field, Arena* arena,
|
||||
MessageLite* msg) {
|
||||
switch (field.processing_type & kTypeMask) {
|
||||
case WireFormatLite::TYPE_MESSAGE:
|
||||
if (arena == NULL) {
|
||||
delete *Raw<MessageLite*>(msg, field.offset);
|
||||
}
|
||||
break;
|
||||
|
||||
case WireFormatLite::TYPE_STRING:
|
||||
case WireFormatLite::TYPE_BYTES:
|
||||
Raw<ArenaStringPtr>(msg, field.offset)
|
||||
->Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), arena);
|
||||
break;
|
||||
|
||||
default:
|
||||
// No cleanup needed.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Clears and reinitializes a oneof field as necessary, in preparation for
|
||||
// parsing a new value with type field_type and field number field_number.
|
||||
//
|
||||
// Note: the oneof_case argument should point directly to the _oneof_case_
|
||||
// element corresponding to this particular oneof, not to the beginning of the
|
||||
// _oneof_case_ array.
|
||||
template <ProcessingType field_type>
|
||||
inline void ResetOneofField(const ParseTable& table, int field_number,
|
||||
Arena* arena, MessageLite* msg, uint32* oneof_case,
|
||||
int64 offset, const void* default_ptr) {
|
||||
if (*oneof_case == field_number) {
|
||||
// The oneof is already set to the right type, so there is no need to clear
|
||||
// it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (*oneof_case != 0) {
|
||||
ClearOneofField(table.fields[*oneof_case], arena, msg);
|
||||
}
|
||||
*oneof_case = field_number;
|
||||
|
||||
switch (field_type) {
|
||||
case ProcessingType_STRING:
|
||||
Raw<ArenaStringPtr>(msg, offset)
|
||||
->UnsafeSetDefault(static_cast<const string*>(default_ptr));
|
||||
break;
|
||||
case ProcessingType_MESSAGE:
|
||||
MessageLite** submessage = Raw<MessageLite*>(msg, offset);
|
||||
const MessageLite* prototype =
|
||||
table.aux[field_number].messages.default_message();
|
||||
*submessage = prototype->New(arena);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <Cardinality cardinality, bool validate, StringType ctype>
|
||||
static inline bool HandleString(io::CodedInputStream* input, MessageLite* msg,
|
||||
Arena* arena, uint32* has_bits,
|
||||
uint32 has_bit_index, int64 offset,
|
||||
const void* default_ptr,
|
||||
const char* field_name) {
|
||||
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
const char* sdata;
|
||||
size_t size;
|
||||
#endif
|
||||
|
||||
string* value;
|
||||
switch (cardinality) {
|
||||
case Cardinality_SINGULAR:
|
||||
// TODO(ckennelly): Is this optimal?
|
||||
value =
|
||||
MutableField<ArenaStringPtr>(msg, has_bits, has_bit_index, offset)
|
||||
->Mutable(static_cast<const string*>(default_ptr), arena);
|
||||
break;
|
||||
case Cardinality_REPEATED:
|
||||
value = AddField<string>(msg, offset);
|
||||
break;
|
||||
case Cardinality_ONEOF:
|
||||
value = Raw<ArenaStringPtr>(msg, offset)
|
||||
->Mutable(static_cast<const string*>(default_ptr), arena);
|
||||
break;
|
||||
}
|
||||
GOOGLE_DCHECK(value != NULL);
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadString(input, value))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
sdata = value->data();
|
||||
size = value->size();
|
||||
#endif
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
if (validate) {
|
||||
WireFormatLite::VerifyUtf8String(sdata, size, WireFormatLite::PARSE,
|
||||
field_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename UnknownFieldHandler, typename InternalMetadata,
|
||||
Cardinality cardinality>
|
||||
inline bool HandleEnum(const ParseTable& table, io::CodedInputStream* input,
|
||||
MessageLite* msg, uint32* presence,
|
||||
uint32 presence_index, int64 offset, uint32 tag,
|
||||
int field_number) {
|
||||
int value;
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
|
||||
input, &value)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AuxillaryParseTableField::EnumValidator validator =
|
||||
table.aux[field_number].enums.validator;
|
||||
if (validator(value)) {
|
||||
switch (cardinality) {
|
||||
case Cardinality_SINGULAR:
|
||||
SetField(msg, presence, presence_index, offset, value);
|
||||
break;
|
||||
case Cardinality_REPEATED:
|
||||
AddField(msg, offset, value);
|
||||
break;
|
||||
case Cardinality_ONEOF:
|
||||
ClearOneofField(table.fields[presence[presence_index]],
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset),
|
||||
msg);
|
||||
SetOneofField(msg, presence, presence_index, offset, field_number,
|
||||
value);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
UnknownFieldHandler::Varint(msg, table, tag, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// RepeatedMessageTypeHandler allows us to operate on RepeatedPtrField fields
|
||||
// without instantiating the specific template.
|
||||
class RepeatedMessageTypeHandler {
|
||||
public:
|
||||
typedef MessageLite Type;
|
||||
static Arena* GetArena(Type* t) { return t->GetArena(); }
|
||||
static void* GetMaybeArenaPointer(Type* t) {
|
||||
return t->GetMaybeArenaPointer();
|
||||
}
|
||||
static inline Type* NewFromPrototype(const Type* prototype,
|
||||
Arena* arena = NULL) {
|
||||
return prototype->New(arena);
|
||||
}
|
||||
static void Delete(Type* t, Arena* arena = NULL) {
|
||||
if (arena == NULL) {
|
||||
delete t;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline bool ReadGroup(int field_number, io::CodedInputStream* input,
|
||||
MessageLite* value) {
|
||||
if (GOOGLE_PREDICT_FALSE(!input->IncrementRecursionDepth())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!value->MergePartialFromCodedStream(input))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
input->DecrementRecursionDepth();
|
||||
// Make sure the last thing read was an end tag for this group.
|
||||
if (GOOGLE_PREDICT_FALSE(!input->LastTagWas(WireFormatLite::MakeTag(
|
||||
field_number, WireFormatLite::WIRETYPE_END_GROUP)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool ReadMessage(io::CodedInputStream* input, MessageLite* value) {
|
||||
int length;
|
||||
if (GOOGLE_PREDICT_FALSE(!input->ReadVarintSizeAsInt(&length))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::pair<io::CodedInputStream::Limit, int> p =
|
||||
input->IncrementRecursionDepthAndPushLimit(length);
|
||||
if (GOOGLE_PREDICT_FALSE(p.second < 0 ||
|
||||
!value->MergePartialFromCodedStream(input))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure that parsing stopped when the limit was hit, not at an endgroup
|
||||
// tag.
|
||||
return input->DecrementRecursionDepthAndPopLimit(p.first);
|
||||
}
|
||||
|
||||
class MergePartialFromCodedStreamHelper {
|
||||
public:
|
||||
static MessageLite* Add(RepeatedPtrFieldBase* field,
|
||||
const MessageLite* prototype) {
|
||||
return field->Add<RepeatedMessageTypeHandler>(
|
||||
const_cast<MessageLite*>(prototype));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename UnknownFieldHandler, typename InternalMetadata>
|
||||
bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table,
|
||||
io::CodedInputStream* input) {
|
||||
// We require that has_bits are present, as to avoid having to check for them
|
||||
// for every field.
|
||||
//
|
||||
// TODO(ckennelly): Make this a compile-time parameter with templates.
|
||||
GOOGLE_DCHECK_GE(table.has_bits_offset, 0);
|
||||
uint32* has_bits = Raw<uint32>(msg, table.has_bits_offset);
|
||||
GOOGLE_DCHECK(has_bits != NULL);
|
||||
|
||||
while (true) {
|
||||
uint32 tag = input->ReadTag();
|
||||
|
||||
const WireFormatLite::WireType wire_type =
|
||||
WireFormatLite::GetTagWireType(tag);
|
||||
const int field_number = WireFormatLite::GetTagFieldNumber(tag);
|
||||
|
||||
if (field_number > table.max_field_number) {
|
||||
// check for possible extensions
|
||||
if (UnknownFieldHandler::ParseExtension(msg, table, input, tag)) {
|
||||
// successfully parsed
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!UnknownFieldHandler::Skip(msg, table, input, tag))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// We implicitly verify that data points to a valid field as we check the
|
||||
// wire types. Entries in table.fields[i] that do not correspond to valid
|
||||
// field numbers have their normal_wiretype and packed_wiretype fields set
|
||||
// with the kInvalidMask value. As wire_type cannot take on that value, we
|
||||
// will never match.
|
||||
const ParseTableField* data = table.fields + field_number;
|
||||
|
||||
// TODO(ckennelly): Avoid sign extension
|
||||
const int64 presence_index = data->presence_index;
|
||||
const int64 offset = data->offset;
|
||||
const unsigned char processing_type = data->processing_type;
|
||||
|
||||
if (data->normal_wiretype == static_cast<unsigned char>(wire_type)) {
|
||||
// TODO(ckennelly): Use a computed goto on GCC/LLVM or otherwise eliminate
|
||||
// the bounds check on processing_type.
|
||||
|
||||
switch (processing_type) {
|
||||
#define HANDLE_TYPE(TYPE, CPPTYPE) \
|
||||
case (WireFormatLite::TYPE_##TYPE): { \
|
||||
CPPTYPE value; \
|
||||
if (GOOGLE_PREDICT_FALSE( \
|
||||
(!WireFormatLite::ReadPrimitive< \
|
||||
CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)))) { \
|
||||
return false; \
|
||||
} \
|
||||
SetField(msg, has_bits, presence_index, offset, value); \
|
||||
break; \
|
||||
} \
|
||||
case (WireFormatLite::TYPE_##TYPE) | kRepeatedMask: { \
|
||||
google::protobuf::RepeatedField<CPPTYPE>* values = \
|
||||
Raw<google::protobuf::RepeatedField<CPPTYPE> >(msg, offset); \
|
||||
if (GOOGLE_PREDICT_FALSE((!WireFormatLite::ReadRepeatedPrimitive< \
|
||||
CPPTYPE, WireFormatLite::TYPE_##TYPE>( \
|
||||
data->tag_size, tag, input, values)))) { \
|
||||
return false; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
case (WireFormatLite::TYPE_##TYPE) | kOneofMask: { \
|
||||
uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset); \
|
||||
CPPTYPE value; \
|
||||
if (GOOGLE_PREDICT_FALSE( \
|
||||
(!WireFormatLite::ReadPrimitive< \
|
||||
CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)))) { \
|
||||
return false; \
|
||||
} \
|
||||
ClearOneofField(table.fields[oneof_case[presence_index]], \
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset), msg); \
|
||||
SetOneofField(msg, oneof_case, presence_index, offset, field_number, \
|
||||
value); \
|
||||
break; \
|
||||
}
|
||||
|
||||
HANDLE_TYPE(INT32, int32)
|
||||
HANDLE_TYPE(INT64, int64)
|
||||
HANDLE_TYPE(SINT32, int32)
|
||||
HANDLE_TYPE(SINT64, int64)
|
||||
HANDLE_TYPE(UINT32, uint32)
|
||||
HANDLE_TYPE(UINT64, uint64)
|
||||
|
||||
HANDLE_TYPE(FIXED32, uint32)
|
||||
HANDLE_TYPE(FIXED64, uint64)
|
||||
HANDLE_TYPE(SFIXED32, int32)
|
||||
HANDLE_TYPE(SFIXED64, int64)
|
||||
|
||||
HANDLE_TYPE(FLOAT, float)
|
||||
HANDLE_TYPE(DOUBLE, double)
|
||||
|
||||
HANDLE_TYPE(BOOL, bool)
|
||||
#undef HANDLE_TYPE
|
||||
case WireFormatLite::TYPE_BYTES:
|
||||
#ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
case WireFormatLite::TYPE_STRING:
|
||||
#endif
|
||||
{
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
const void* default_ptr = table.aux[field_number].strings.default_ptr;
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE((
|
||||
!HandleString<Cardinality_SINGULAR, false, StringType_STRING>(
|
||||
input, msg, arena, has_bits, presence_index, offset,
|
||||
default_ptr, NULL)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_BYTES | kOneofMask:
|
||||
#ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
case WireFormatLite::TYPE_STRING | kOneofMask:
|
||||
#endif
|
||||
{
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset);
|
||||
const void* default_ptr = table.aux[field_number].strings.default_ptr;
|
||||
|
||||
ResetOneofField<ProcessingType_STRING>(
|
||||
table, field_number, arena, msg, oneof_case + presence_index,
|
||||
offset, default_ptr);
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!HandleString<Cardinality_ONEOF, false, StringType_STRING>(
|
||||
input, msg, arena, has_bits, presence_index, offset,
|
||||
default_ptr, NULL)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (WireFormatLite::TYPE_BYTES) | kRepeatedMask:
|
||||
#ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
case (WireFormatLite::TYPE_STRING) | kRepeatedMask:
|
||||
#endif
|
||||
{
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
const void* default_ptr =
|
||||
table.aux[field_number].strings.default_ptr;
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE((
|
||||
!HandleString<Cardinality_REPEATED, false, StringType_STRING>(
|
||||
input, msg, arena, has_bits, presence_index, offset,
|
||||
default_ptr, NULL)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
case (WireFormatLite::TYPE_STRING): {
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
const void* default_ptr = table.aux[field_number].strings.default_ptr;
|
||||
const char* field_name = table.aux[field_number].strings.field_name;
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!HandleString<Cardinality_SINGULAR, true, StringType_STRING>(
|
||||
input, msg, arena, has_bits, presence_index, offset,
|
||||
default_ptr, field_name)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (WireFormatLite::TYPE_STRING) | kRepeatedMask: {
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
const void* default_ptr = table.aux[field_number].strings.default_ptr;
|
||||
const char* field_name = table.aux[field_number].strings.field_name;
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!HandleString<Cardinality_REPEATED, true, StringType_STRING>(
|
||||
input, msg, arena, has_bits, presence_index, offset,
|
||||
default_ptr, field_name)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (WireFormatLite::TYPE_STRING) | kOneofMask: {
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset);
|
||||
const void* default_ptr = table.aux[field_number].strings.default_ptr;
|
||||
const char* field_name = table.aux[field_number].strings.field_name;
|
||||
|
||||
ResetOneofField<ProcessingType_STRING>(
|
||||
table, field_number, arena, msg, oneof_case + presence_index,
|
||||
offset, default_ptr);
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!HandleString<Cardinality_ONEOF, true, StringType_STRING>(
|
||||
input, msg, arena, has_bits, presence_index, offset,
|
||||
default_ptr, field_name)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case WireFormatLite::TYPE_ENUM: {
|
||||
if (GOOGLE_PREDICT_FALSE((!HandleEnum<UnknownFieldHandler, InternalMetadata,
|
||||
Cardinality_SINGULAR>(
|
||||
table, input, msg, has_bits, presence_index, offset, tag,
|
||||
field_number)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_ENUM | kRepeatedMask: {
|
||||
if (GOOGLE_PREDICT_FALSE((!HandleEnum<UnknownFieldHandler, InternalMetadata,
|
||||
Cardinality_REPEATED>(
|
||||
table, input, msg, has_bits, presence_index, offset, tag,
|
||||
field_number)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_ENUM | kOneofMask: {
|
||||
uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset);
|
||||
if (GOOGLE_PREDICT_FALSE((!HandleEnum<UnknownFieldHandler, InternalMetadata,
|
||||
Cardinality_ONEOF>(
|
||||
table, input, msg, oneof_case, presence_index, offset, tag,
|
||||
field_number)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_GROUP: {
|
||||
MessageLite** submsg_holder =
|
||||
MutableField<MessageLite*>(msg, has_bits, presence_index, offset);
|
||||
MessageLite* submsg = *submsg_holder;
|
||||
|
||||
if (submsg == NULL) {
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
const MessageLite* prototype =
|
||||
table.aux[field_number].messages.default_message();
|
||||
submsg = prototype->New(arena);
|
||||
*submsg_holder = submsg;
|
||||
}
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadGroup(
|
||||
field_number, input, submsg))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_GROUP | kRepeatedMask: {
|
||||
RepeatedPtrFieldBase* field = Raw<RepeatedPtrFieldBase>(msg, offset);
|
||||
const MessageLite* prototype =
|
||||
table.aux[field_number].messages.default_message();
|
||||
GOOGLE_DCHECK(prototype != NULL);
|
||||
|
||||
MessageLite* submsg =
|
||||
MergePartialFromCodedStreamHelper::Add(field, prototype);
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadGroup(
|
||||
field_number, input, submsg))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_MESSAGE: {
|
||||
MessageLite** submsg_holder =
|
||||
MutableField<MessageLite*>(msg, has_bits, presence_index, offset);
|
||||
MessageLite* submsg = *submsg_holder;
|
||||
|
||||
if (submsg == NULL) {
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
const MessageLite* prototype =
|
||||
table.aux[field_number].messages.default_message();
|
||||
submsg = prototype->New(arena);
|
||||
*submsg_holder = submsg;
|
||||
}
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadMessage(input, submsg))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
// TODO(ckennelly): Adapt ReadMessageNoVirtualNoRecursionDepth and
|
||||
// manage input->IncrementRecursionDepth() here.
|
||||
case WireFormatLite::TYPE_MESSAGE | kRepeatedMask: {
|
||||
RepeatedPtrFieldBase* field = Raw<RepeatedPtrFieldBase>(msg, offset);
|
||||
const MessageLite* prototype =
|
||||
table.aux[field_number].messages.default_message();
|
||||
GOOGLE_DCHECK(prototype != NULL);
|
||||
|
||||
MessageLite* submsg =
|
||||
MergePartialFromCodedStreamHelper::Add(field, prototype);
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadMessage(input, submsg))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_MESSAGE | kOneofMask: {
|
||||
Arena* const arena =
|
||||
GetArena<InternalMetadata>(msg, table.arena_offset);
|
||||
uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset);
|
||||
MessageLite** submsg_holder = Raw<MessageLite*>(msg, offset);
|
||||
ResetOneofField<ProcessingType_MESSAGE>(
|
||||
table, field_number, arena, msg, oneof_case + presence_index,
|
||||
offset, NULL);
|
||||
MessageLite* submsg = *submsg_holder;
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadMessage(input, submsg))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case TYPE_MAP: {
|
||||
if (GOOGLE_PREDICT_FALSE(!(*table.aux[field_number].maps.parse_map)(
|
||||
input, Raw<void>(msg, offset)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0: {
|
||||
// Done.
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (data->packed_wiretype == static_cast<unsigned char>(wire_type)) {
|
||||
// Non-packable fields have their packed_wiretype masked with
|
||||
// kNotPackedMask, which is impossible to match here.
|
||||
GOOGLE_DCHECK(processing_type & kRepeatedMask);
|
||||
GOOGLE_DCHECK_NE(processing_type, kRepeatedMask);
|
||||
GOOGLE_DCHECK_EQ(0, processing_type & kOneofMask);
|
||||
|
||||
|
||||
|
||||
// TODO(ckennelly): Use a computed goto on GCC/LLVM.
|
||||
//
|
||||
// Mask out kRepeatedMask bit, allowing the jump table to be smaller.
|
||||
switch (static_cast<WireFormatLite::FieldType>(
|
||||
processing_type ^ kRepeatedMask)) {
|
||||
#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \
|
||||
case WireFormatLite::TYPE_##TYPE: { \
|
||||
google::protobuf::RepeatedField<CPPTYPE>* values = \
|
||||
Raw<google::protobuf::RepeatedField<CPPTYPE> >(msg, offset); \
|
||||
if (GOOGLE_PREDICT_FALSE( \
|
||||
(!WireFormatLite::ReadPackedPrimitive< \
|
||||
CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, values)))) { \
|
||||
return false; \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
|
||||
HANDLE_PACKED_TYPE(INT32, int32, Int32)
|
||||
HANDLE_PACKED_TYPE(INT64, int64, Int64)
|
||||
HANDLE_PACKED_TYPE(SINT32, int32, Int32)
|
||||
HANDLE_PACKED_TYPE(SINT64, int64, Int64)
|
||||
HANDLE_PACKED_TYPE(UINT32, uint32, UInt32)
|
||||
HANDLE_PACKED_TYPE(UINT64, uint64, UInt64)
|
||||
|
||||
HANDLE_PACKED_TYPE(FIXED32, uint32, UInt32)
|
||||
HANDLE_PACKED_TYPE(FIXED64, uint64, UInt64)
|
||||
HANDLE_PACKED_TYPE(SFIXED32, int32, Int32)
|
||||
HANDLE_PACKED_TYPE(SFIXED64, int64, Int64)
|
||||
|
||||
HANDLE_PACKED_TYPE(FLOAT, float, Float)
|
||||
HANDLE_PACKED_TYPE(DOUBLE, double, Double)
|
||||
|
||||
HANDLE_PACKED_TYPE(BOOL, bool, Bool)
|
||||
#undef HANDLE_PACKED_TYPE
|
||||
case WireFormatLite::TYPE_ENUM: {
|
||||
// To avoid unnecessarily calling MutableUnknownFields (which mutates
|
||||
// InternalMetadataWithArena) when all inputs in the repeated series
|
||||
// are valid, we implement our own parser rather than call
|
||||
// WireFormat::ReadPackedEnumPreserveUnknowns.
|
||||
uint32 length;
|
||||
if (GOOGLE_PREDICT_FALSE(!input->ReadVarint32(&length))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AuxillaryParseTableField::EnumValidator validator =
|
||||
table.aux[field_number].enums.validator;
|
||||
google::protobuf::RepeatedField<int>* values =
|
||||
Raw<google::protobuf::RepeatedField<int> >(msg, offset);
|
||||
|
||||
io::CodedInputStream::Limit limit = input->PushLimit(length);
|
||||
while (input->BytesUntilLimit() > 0) {
|
||||
int value;
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!google::protobuf::internal::WireFormatLite::ReadPrimitive<
|
||||
int, WireFormatLite::TYPE_ENUM>(input, &value)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (validator(value)) {
|
||||
values->Add(value);
|
||||
} else {
|
||||
// TODO(ckennelly): Consider caching here.
|
||||
UnknownFieldHandler::Varint(msg, table, tag, value);
|
||||
}
|
||||
}
|
||||
input->PopLimit(limit);
|
||||
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_STRING:
|
||||
case WireFormatLite::TYPE_GROUP:
|
||||
case WireFormatLite::TYPE_MESSAGE:
|
||||
case WireFormatLite::TYPE_BYTES:
|
||||
GOOGLE_DCHECK(false);
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
|
||||
// Must be the end of the message.
|
||||
return true;
|
||||
}
|
||||
|
||||
// check for possible extensions
|
||||
if (UnknownFieldHandler::ParseExtension(msg, table, input, tag)) {
|
||||
// successfully parsed
|
||||
continue;
|
||||
}
|
||||
|
||||
// process unknown field.
|
||||
if (GOOGLE_PREDICT_FALSE(!UnknownFieldHandler::Skip(msg, table, input, tag))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_LITE_H__
|
||||
@@ -0,0 +1,139 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file contains declarations needed in generated headers for messages
|
||||
// that use tail-call table parsing. Everything in this file is for internal
|
||||
// use only.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
// Must come last:
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Additional information about this field:
|
||||
struct TcFieldData {
|
||||
constexpr TcFieldData() : data(0) {}
|
||||
constexpr TcFieldData(uint16_t coded_tag, uint8_t hasbit_idx, uint16_t offset)
|
||||
: data(static_cast<uint64_t>(offset) << 48 |
|
||||
static_cast<uint64_t>(hasbit_idx) << 16 | coded_tag) {}
|
||||
|
||||
template <typename TagType = uint16_t>
|
||||
TagType coded_tag() const {
|
||||
return static_cast<TagType>(data);
|
||||
}
|
||||
uint8_t hasbit_idx() const { return static_cast<uint8_t>(data >> 16); }
|
||||
uint16_t offset() const { return static_cast<uint16_t>(data >> 48); }
|
||||
|
||||
uint64_t data;
|
||||
};
|
||||
|
||||
struct TcParseTableBase;
|
||||
|
||||
// TailCallParseFunc is the function pointer type used in the tailcall table.
|
||||
typedef const char* (*TailCallParseFunc)(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_WIN64)
|
||||
#pragma warning(push)
|
||||
// TcParseTableBase is intentionally overaligned on 32 bit targets.
|
||||
#pragma warning(disable : 4324)
|
||||
#endif
|
||||
|
||||
// Base class for message-level table with info for the tail-call parser.
|
||||
struct alignas(uint64_t) TcParseTableBase {
|
||||
// Common attributes for message layout:
|
||||
uint16_t has_bits_offset;
|
||||
uint16_t extension_offset;
|
||||
uint32_t extension_range_low;
|
||||
uint32_t extension_range_high;
|
||||
uint8_t fast_idx_mask;
|
||||
uint8_t reserved;
|
||||
uint16_t num_fields;
|
||||
const MessageLite* default_instance;
|
||||
|
||||
// Handler for fields which are not handled by table dispatch.
|
||||
TailCallParseFunc fallback;
|
||||
|
||||
// Table entry for fast-path tailcall dispatch handling.
|
||||
struct FastFieldEntry {
|
||||
// Target function for dispatch:
|
||||
TailCallParseFunc target;
|
||||
// Field data used during parse:
|
||||
TcFieldData bits;
|
||||
};
|
||||
// There is always at least one table entry.
|
||||
const FastFieldEntry* fast_entry(size_t idx) const {
|
||||
return reinterpret_cast<const FastFieldEntry*>(this + 1) + idx;
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_WIN64)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
static_assert(sizeof(TcParseTableBase::FastFieldEntry) <= 16,
|
||||
"Field entry is too big.");
|
||||
|
||||
template <size_t kFastTableSizeLog2>
|
||||
struct TcParseTable {
|
||||
TcParseTableBase header;
|
||||
|
||||
// Entries for each field.
|
||||
//
|
||||
// Fields are indexed by the lowest bits of their field number. The field
|
||||
// number is masked to fit inside the table. Note that the parsing logic
|
||||
// generally calls `TailCallParseTableBase::table()` instead of accessing
|
||||
// this field directly.
|
||||
TcParseTableBase::FastFieldEntry entries[(1 << kFastTableSizeLog2)];
|
||||
};
|
||||
|
||||
static_assert(std::is_standard_layout<TcParseTable<1>>::value,
|
||||
"TcParseTable must be standard layout.");
|
||||
|
||||
static_assert(offsetof(TcParseTable<1>, entries) == sizeof(TcParseTableBase),
|
||||
"Table entries must be laid out after TcParseTableBase.");
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
|
||||
@@ -0,0 +1,302 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/generated_message_tctable_decl.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
// Must come last:
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Message;
|
||||
class UnknownFieldSet;
|
||||
|
||||
namespace internal {
|
||||
|
||||
// PROTOBUF_TC_PARAM_DECL are the parameters for tailcall functions, it is
|
||||
// defined in port_def.inc.
|
||||
//
|
||||
// Note that this is performance sensitive: changing the parameters will change
|
||||
// the registers used by the ABI calling convention, which subsequently affects
|
||||
// register selection logic inside the function.
|
||||
|
||||
// PROTOBUF_TC_PARAM_PASS passes values to match PROTOBUF_TC_PARAM_DECL.
|
||||
#define PROTOBUF_TC_PARAM_PASS msg, ptr, ctx, table, hasbits, data
|
||||
|
||||
// PROTOBUF_TC_PARSE_* decide which function is used to parse message-typed
|
||||
// fields. The guard macros are defined in port_def.inc.
|
||||
#if PROTOBUF_TC_STATIC_PARSE_SINGULAR1
|
||||
#define PROTOBUF_TC_PARSE_SINGULAR1(MESSAGE) MESSAGE::Tct_ParseS1
|
||||
#else
|
||||
#define PROTOBUF_TC_PARSE_SINGULAR1(MESSAGE) \
|
||||
::google::protobuf::internal::TcParser::SingularParseMessage<MESSAGE, uint8_t>
|
||||
#endif // PROTOBUF_TC_STATIC_PARSE_SINGULAR1
|
||||
|
||||
#if PROTOBUF_TC_STATIC_PARSE_SINGULAR2
|
||||
#define PROTOBUF_TC_PARSE_SINGULAR2(MESSAGE) MESSAGE::Tct_ParseS2
|
||||
#else
|
||||
#define PROTOBUF_TC_PARSE_SINGULAR2(MESSAGE) \
|
||||
::google::protobuf::internal::TcParser::SingularParseMessage<MESSAGE, uint16_t>
|
||||
#endif // PROTOBUF_TC_STATIC_PARSE_SINGULAR2
|
||||
|
||||
#if PROTOBUF_TC_STATIC_PARSE_REPEATED1
|
||||
#define PROTOBUF_TC_PARSE_REPEATED1(MESSAGE) MESSAGE::Tct_ParseR1
|
||||
#else
|
||||
#define PROTOBUF_TC_PARSE_REPEATED1(MESSAGE) \
|
||||
::google::protobuf::internal::TcParser::RepeatedParseMessage<MESSAGE, uint8_t>
|
||||
#endif // PROTOBUF_TC_STATIC_PARSE_REPEATED1
|
||||
|
||||
#if PROTOBUF_TC_STATIC_PARSE_REPEATED2
|
||||
#define PROTOBUF_TC_PARSE_REPEATED2(MESSAGE) MESSAGE::Tct_ParseR2
|
||||
#else
|
||||
#define PROTOBUF_TC_PARSE_REPEATED2(MESSAGE) \
|
||||
::google::protobuf::internal::TcParser::RepeatedParseMessage<MESSAGE, uint16_t>
|
||||
#endif // PROTOBUF_TC_STATIC_PARSE_REPEATED2
|
||||
|
||||
#ifndef NDEBUG
|
||||
template <size_t align>
|
||||
#ifndef _MSC_VER
|
||||
[[noreturn]]
|
||||
#endif
|
||||
void AlignFail(uintptr_t address) {
|
||||
GOOGLE_LOG(FATAL) << "Unaligned (" << align << ") access at " << address;
|
||||
}
|
||||
|
||||
extern template void AlignFail<4>(uintptr_t);
|
||||
extern template void AlignFail<8>(uintptr_t);
|
||||
#endif
|
||||
|
||||
// TcParser implements most of the parsing logic for tailcall tables.
|
||||
class TcParser final {
|
||||
public:
|
||||
static const char* GenericFallback(PROTOBUF_TC_PARAM_DECL);
|
||||
static const char* GenericFallbackLite(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
// Dispatch to the designated parse function
|
||||
inline PROTOBUF_ALWAYS_INLINE static const char* TagDispatch(
|
||||
PROTOBUF_TC_PARAM_DECL) {
|
||||
const auto coded_tag = UnalignedLoad<uint16_t>(ptr);
|
||||
const size_t idx = coded_tag & table->fast_idx_mask;
|
||||
PROTOBUF_ASSUME((idx & 7) == 0);
|
||||
auto* fast_entry = table->fast_entry(idx >> 3);
|
||||
data = fast_entry->bits;
|
||||
data.data ^= coded_tag;
|
||||
PROTOBUF_MUSTTAIL return fast_entry->target(PROTOBUF_TC_PARAM_PASS);
|
||||
}
|
||||
|
||||
// We can only safely call from field to next field if the call is optimized
|
||||
// to a proper tail call. Otherwise we blow through stack. Clang and gcc
|
||||
// reliably do this optimization in opt mode, but do not perform this in debug
|
||||
// mode. Luckily the structure of the algorithm is such that it's always
|
||||
// possible to just return and use the enclosing parse loop as a trampoline.
|
||||
static const char* ToTagDispatch(PROTOBUF_TC_PARAM_DECL) {
|
||||
constexpr bool always_return = !PROTOBUF_TAILCALL;
|
||||
if (always_return || !ctx->DataAvailable(ptr)) {
|
||||
PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
|
||||
}
|
||||
PROTOBUF_MUSTTAIL return TagDispatch(PROTOBUF_TC_PARAM_PASS);
|
||||
}
|
||||
|
||||
static const char* ParseLoop(MessageLite* msg, const char* ptr,
|
||||
ParseContext* ctx,
|
||||
const TcParseTableBase* table) {
|
||||
ScopedArenaSwap saved(msg, ctx);
|
||||
const uint32_t has_bits_offset = table->has_bits_offset;
|
||||
while (!ctx->Done(&ptr)) {
|
||||
uint64_t hasbits = 0;
|
||||
if (has_bits_offset) hasbits = RefAt<uint32_t>(msg, has_bits_offset);
|
||||
ptr = TagDispatch(msg, ptr, ctx, table, hasbits, {});
|
||||
if (ptr == nullptr) break;
|
||||
if (ctx->LastTag() != 1) break; // Ended on terminating tag
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename FieldType, typename TagType>
|
||||
PROTOBUF_NOINLINE static const char* SingularParseMessage(
|
||||
PROTOBUF_TC_PARAM_DECL) {
|
||||
if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
|
||||
return table->fallback(PROTOBUF_TC_PARAM_PASS);
|
||||
}
|
||||
ptr += sizeof(TagType);
|
||||
hasbits |= (uint64_t{1} << data.hasbit_idx());
|
||||
auto& field = RefAt<FieldType*>(msg, data.offset());
|
||||
if (field == nullptr) {
|
||||
auto arena = ctx->data().arena;
|
||||
if (Arena::is_arena_constructable<FieldType>::value) {
|
||||
field = Arena::CreateMessage<FieldType>(arena);
|
||||
} else {
|
||||
field = Arena::Create<FieldType>(arena);
|
||||
}
|
||||
}
|
||||
SyncHasbits(msg, hasbits, table);
|
||||
return ctx->ParseMessage(field, ptr);
|
||||
}
|
||||
|
||||
template <typename FieldType, typename TagType>
|
||||
PROTOBUF_NOINLINE static const char* RepeatedParseMessage(
|
||||
PROTOBUF_TC_PARAM_DECL) {
|
||||
if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
|
||||
return table->fallback(PROTOBUF_TC_PARAM_PASS);
|
||||
}
|
||||
ptr += sizeof(TagType);
|
||||
auto& field = RefAt<RepeatedPtrField<FieldType>>(msg, data.offset());
|
||||
SyncHasbits(msg, hasbits, table);
|
||||
ptr = ctx->ParseMessage(field.Add(), ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename LayoutType, typename TagType>
|
||||
static const char* SingularFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename LayoutType, typename TagType>
|
||||
static const char* RepeatedFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename LayoutType, typename TagType>
|
||||
static const char* PackedFixed(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
enum VarintDecode { kNoConversion = 0, kZigZag = 1 };
|
||||
template <typename FieldType, typename TagType, VarintDecode zigzag>
|
||||
static const char* SingularVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename FieldType, typename TagType, VarintDecode zigzag>
|
||||
static const char* RepeatedVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename FieldType, typename TagType, VarintDecode zigzag>
|
||||
static const char* PackedVarint(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
enum Utf8Type { kNoUtf8 = 0, kUtf8 = 1, kUtf8ValidateOnly = 2 };
|
||||
template <typename TagType, Utf8Type utf8>
|
||||
static const char* SingularString(PROTOBUF_TC_PARAM_DECL);
|
||||
template <typename TagType, Utf8Type utf8>
|
||||
static const char* RepeatedString(PROTOBUF_TC_PARAM_DECL);
|
||||
|
||||
template <typename T>
|
||||
static inline T& RefAt(void* x, size_t offset) {
|
||||
T* target = reinterpret_cast<T*>(static_cast<char*>(x) + offset);
|
||||
#ifndef NDEBUG
|
||||
if (PROTOBUF_PREDICT_FALSE(
|
||||
reinterpret_cast<uintptr_t>(target) % alignof(T) != 0)) {
|
||||
AlignFail<alignof(T)>(reinterpret_cast<uintptr_t>(target));
|
||||
}
|
||||
#endif
|
||||
return *target;
|
||||
}
|
||||
|
||||
static inline PROTOBUF_ALWAYS_INLINE void SyncHasbits(
|
||||
MessageLite* msg, uint64_t hasbits, const TcParseTableBase* table) {
|
||||
const uint32_t has_bits_offset = table->has_bits_offset;
|
||||
if (has_bits_offset) {
|
||||
// Only the first 32 has-bits are updated. Nothing above those is stored,
|
||||
// but e.g. messages without has-bits update the upper bits.
|
||||
RefAt<uint32_t>(msg, has_bits_offset) = static_cast<uint32_t>(hasbits);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
static inline PROTOBUF_ALWAYS_INLINE const char* ToParseLoop(
|
||||
PROTOBUF_TC_PARAM_DECL) {
|
||||
(void)data;
|
||||
(void)ctx;
|
||||
SyncHasbits(msg, hasbits, table);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static inline PROTOBUF_ALWAYS_INLINE const char* Error(
|
||||
PROTOBUF_TC_PARAM_DECL) {
|
||||
(void)data;
|
||||
(void)ctx;
|
||||
(void)ptr;
|
||||
SyncHasbits(msg, hasbits, table);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
class ScopedArenaSwap final {
|
||||
public:
|
||||
ScopedArenaSwap(MessageLite* msg, ParseContext* ctx)
|
||||
: ctx_(ctx), saved_(ctx->data().arena) {
|
||||
ctx_->data().arena = msg->GetArenaForAllocation();
|
||||
}
|
||||
ScopedArenaSwap(const ScopedArenaSwap&) = delete;
|
||||
~ScopedArenaSwap() { ctx_->data().arena = saved_; }
|
||||
|
||||
private:
|
||||
ParseContext* const ctx_;
|
||||
Arena* const saved_;
|
||||
};
|
||||
|
||||
template <class MessageBaseT, class UnknownFieldsT>
|
||||
static const char* GenericFallbackImpl(PROTOBUF_TC_PARAM_DECL) {
|
||||
#define CHK_(x) \
|
||||
if (PROTOBUF_PREDICT_FALSE(!(x))) return nullptr /* NOLINT */
|
||||
|
||||
SyncHasbits(msg, hasbits, table);
|
||||
uint32_t tag;
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
|
||||
CHK_(ptr);
|
||||
if ((tag & 7) == WireFormatLite::WIRETYPE_END_GROUP || tag == 0) {
|
||||
ctx->SetLastTag(tag);
|
||||
return ptr;
|
||||
}
|
||||
(void)data;
|
||||
uint32_t num = tag >> 3;
|
||||
if (table->extension_range_low <= num &&
|
||||
num <= table->extension_range_high) {
|
||||
return RefAt<ExtensionSet>(msg, table->extension_offset)
|
||||
.ParseField(tag, ptr,
|
||||
static_cast<const MessageBaseT*>(table->default_instance),
|
||||
&msg->_internal_metadata_, ctx);
|
||||
}
|
||||
return UnknownFieldParse(
|
||||
tag, msg->_internal_metadata_.mutable_unknown_fields<UnknownFieldsT>(),
|
||||
ptr, ctx);
|
||||
#undef CHK_
|
||||
}
|
||||
};
|
||||
|
||||
// Declare helper functions:
|
||||
#include <google/protobuf/generated_message_tctable_impl.inc>
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
|
||||
@@ -0,0 +1,92 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// clang-format off
|
||||
#ifdef PROTOBUF_TCT_SOURCE
|
||||
#define PROTOBUF_TCT_EXTERN
|
||||
#else
|
||||
#define PROTOBUF_TCT_EXTERN extern
|
||||
#endif
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::PackedFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::PackedFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::PackedVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::PackedVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kZigZag>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kZigZag>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::PackedVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kZigZag>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kZigZag>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kZigZag>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::PackedVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kZigZag>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::PackedVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoUtf8>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoUtf8>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kUtf8>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kUtf8>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kUtf8ValidateOnly>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kUtf8ValidateOnly>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::PackedFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::PackedFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::PackedVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::PackedVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kZigZag>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kZigZag>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::PackedVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kZigZag>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kZigZag>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kZigZag>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::PackedVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kZigZag>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::PackedVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoUtf8>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kNoUtf8>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kUtf8>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kUtf8>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::SingularString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kUtf8ValidateOnly>(PROTOBUF_TC_PARAM_DECL);
|
||||
PROTOBUF_TCT_EXTERN template const char* TcParser::RepeatedString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParser::kUtf8ValidateOnly>(PROTOBUF_TC_PARAM_DECL);
|
||||
#undef PROTOBUF_TCT_EXTERN
|
||||
// clang-format on
|
||||
+188
-139
@@ -34,44 +34,63 @@
|
||||
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/io/coded_stream_inl.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/generated_message_table_driven.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
|
||||
// Must be included last
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
PROTOBUF_PRAGMA_INIT_SEG
|
||||
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
|
||||
double Infinity() {
|
||||
return std::numeric_limits<double>::infinity();
|
||||
void DestroyMessage(const void* message) {
|
||||
static_cast<const MessageLite*>(message)->~MessageLite();
|
||||
}
|
||||
double NaN() {
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
void DestroyString(const void* s) {
|
||||
static_cast<const std::string*>(s)->~basic_string();
|
||||
}
|
||||
|
||||
ExplicitlyConstructed< ::std::string> fixed_address_empty_string;
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(empty_string_once_init_);
|
||||
PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
|
||||
PROTOBUF_ATTRIBUTE_INIT_PRIORITY ExplicitlyConstructed<std::string>
|
||||
fixed_address_empty_string{}; // NOLINT
|
||||
|
||||
void DeleteEmptyString() { fixed_address_empty_string.Destruct(); }
|
||||
|
||||
void InitEmptyString() {
|
||||
PROTOBUF_CONSTINIT std::atomic<bool> init_protobuf_defaults_state{false};
|
||||
static bool InitProtobufDefaultsImpl() {
|
||||
fixed_address_empty_string.DefaultConstruct();
|
||||
OnShutdown(&DeleteEmptyString);
|
||||
OnShutdownDestroyString(fixed_address_empty_string.get_mutable());
|
||||
|
||||
|
||||
init_protobuf_defaults_state.store(true, std::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t StringSpaceUsedExcludingSelfLong(const string& str) {
|
||||
void InitProtobufDefaultsSlow() {
|
||||
static bool is_inited = InitProtobufDefaultsImpl();
|
||||
(void)is_inited;
|
||||
}
|
||||
// Force the initialization of the empty string.
|
||||
// Normally, registration would do it, but we don't have any guarantee that
|
||||
// there is any object with reflection.
|
||||
PROTOBUF_ATTRIBUTE_INIT_PRIORITY static std::true_type init_empty_string =
|
||||
(InitProtobufDefaultsSlow(), std::true_type{});
|
||||
|
||||
size_t StringSpaceUsedExcludingSelfLong(const std::string& str) {
|
||||
const void* start = &str;
|
||||
const void* end = &str + 1;
|
||||
if (start <= str.data() && str.data() < end) {
|
||||
@@ -82,12 +101,6 @@ size_t StringSpaceUsedExcludingSelfLong(const string& str) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void InitProtobufDefaults() {
|
||||
GetEmptyString();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T& Get(const void* ptr) {
|
||||
return *static_cast<const T*>(ptr);
|
||||
@@ -103,105 +116,96 @@ struct PrimitiveTypeHelper;
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_BOOL> {
|
||||
typedef bool Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
static void Serialize(const void* ptr, io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteBoolNoTag(Get<bool>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
|
||||
return WireFormatLite::WriteBoolNoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {
|
||||
typedef int32 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteInt32NoTag(Get<int32>(ptr), output);
|
||||
typedef int32_t Type;
|
||||
static void Serialize(const void* ptr, io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteInt32NoTag(Get<int32_t>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
|
||||
return WireFormatLite::WriteInt32NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT32> {
|
||||
typedef int32 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteSInt32NoTag(Get<int32>(ptr), output);
|
||||
typedef int32_t Type;
|
||||
static void Serialize(const void* ptr, io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteSInt32NoTag(Get<int32_t>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
|
||||
return WireFormatLite::WriteSInt32NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT32> {
|
||||
typedef uint32 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteUInt32NoTag(Get<uint32>(ptr), output);
|
||||
typedef uint32_t Type;
|
||||
static void Serialize(const void* ptr, io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteUInt32NoTag(Get<uint32_t>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
|
||||
return WireFormatLite::WriteUInt32NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT64> {
|
||||
typedef int64 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteInt64NoTag(Get<int64>(ptr), output);
|
||||
typedef int64_t Type;
|
||||
static void Serialize(const void* ptr, io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteInt64NoTag(Get<int64_t>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
|
||||
return WireFormatLite::WriteInt64NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT64> {
|
||||
typedef int64 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteSInt64NoTag(Get<int64>(ptr), output);
|
||||
typedef int64_t Type;
|
||||
static void Serialize(const void* ptr, io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteSInt64NoTag(Get<int64_t>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
|
||||
return WireFormatLite::WriteSInt64NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT64> {
|
||||
typedef uint64 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteUInt64NoTag(Get<uint64>(ptr), output);
|
||||
typedef uint64_t Type;
|
||||
static void Serialize(const void* ptr, io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteUInt64NoTag(Get<uint64_t>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
|
||||
return WireFormatLite::WriteUInt64NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
|
||||
typedef uint32 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteFixed32NoTag(Get<uint32>(ptr), output);
|
||||
typedef uint32_t Type;
|
||||
static void Serialize(const void* ptr, io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteFixed32NoTag(Get<uint32_t>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
|
||||
return WireFormatLite::WriteFixed32NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
|
||||
typedef uint64 Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteFixed64NoTag(Get<uint64>(ptr), output);
|
||||
typedef uint64_t Type;
|
||||
static void Serialize(const void* ptr, io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteFixed64NoTag(Get<uint64_t>(ptr), output);
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
|
||||
return WireFormatLite::WriteFixed64NoTagToArray(Get<Type>(ptr), buffer);
|
||||
}
|
||||
};
|
||||
@@ -213,12 +217,12 @@ struct PrimitiveTypeHelper<WireFormatLite::TYPE_ENUM>
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED32>
|
||||
: PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
|
||||
typedef int32 Type;
|
||||
typedef int32_t Type;
|
||||
};
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED64>
|
||||
: PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
|
||||
typedef int64 Type;
|
||||
typedef int64_t Type;
|
||||
};
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_FLOAT>
|
||||
@@ -233,14 +237,13 @@ struct PrimitiveTypeHelper<WireFormatLite::TYPE_DOUBLE>
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {
|
||||
typedef string Type;
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
typedef std::string Type;
|
||||
static void Serialize(const void* ptr, io::CodedOutputStream* output) {
|
||||
const Type& value = *static_cast<const Type*>(ptr);
|
||||
output->WriteVarint32(value.size());
|
||||
output->WriteRawMaybeAliased(value.data(), value.size());
|
||||
}
|
||||
static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
|
||||
static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
|
||||
const Type& value = *static_cast<const Type*>(ptr);
|
||||
return io::CodedOutputStream::WriteStringWithSizeToArray(value, buffer);
|
||||
}
|
||||
@@ -251,6 +254,10 @@ struct PrimitiveTypeHelper<WireFormatLite::TYPE_BYTES>
|
||||
: PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {};
|
||||
|
||||
|
||||
template <>
|
||||
struct PrimitiveTypeHelper<FieldMetadata::kInlinedType>
|
||||
: PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {};
|
||||
|
||||
// We want to serialize to both CodedOutputStream and directly into byte arrays
|
||||
// without duplicating the code. In fact we might want extra output channels in
|
||||
// the future.
|
||||
@@ -263,27 +270,26 @@ void SerializeTo(const void* ptr, O* output) {
|
||||
}
|
||||
|
||||
template <typename O>
|
||||
void WriteTagTo(uint32 tag, O* output) {
|
||||
void WriteTagTo(uint32_t tag, O* output) {
|
||||
SerializeTo<WireFormatLite::TYPE_UINT32>(&tag, output);
|
||||
}
|
||||
|
||||
template <typename O>
|
||||
void WriteLengthTo(uint32 length, O* output) {
|
||||
void WriteLengthTo(uint32_t length, O* output) {
|
||||
SerializeTo<WireFormatLite::TYPE_UINT32>(&length, output);
|
||||
}
|
||||
|
||||
// Specialization for coded output stream
|
||||
template <int type>
|
||||
struct OutputHelper< ::google::protobuf::io::CodedOutputStream, type> {
|
||||
static void Serialize(const void* ptr,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
struct OutputHelper<io::CodedOutputStream, type> {
|
||||
static void Serialize(const void* ptr, io::CodedOutputStream* output) {
|
||||
PrimitiveTypeHelper<type>::Serialize(ptr, output);
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization for writing into a plain array
|
||||
struct ArrayOutput {
|
||||
uint8* ptr;
|
||||
uint8_t* ptr;
|
||||
bool is_deterministic;
|
||||
};
|
||||
|
||||
@@ -295,38 +301,32 @@ struct OutputHelper<ArrayOutput, type> {
|
||||
};
|
||||
|
||||
void SerializeMessageNoTable(const MessageLite* msg,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
io::CodedOutputStream* output) {
|
||||
msg->SerializeWithCachedSizes(output);
|
||||
}
|
||||
|
||||
void SerializeMessageNoTable(const MessageLite* msg, ArrayOutput* output) {
|
||||
output->ptr = msg->InternalSerializeWithCachedSizesToArray(
|
||||
output->is_deterministic, output->ptr);
|
||||
io::ArrayOutputStream array_stream(output->ptr, INT_MAX);
|
||||
io::CodedOutputStream o(&array_stream);
|
||||
o.SetSerializationDeterministic(output->is_deterministic);
|
||||
msg->SerializeWithCachedSizes(&o);
|
||||
output->ptr += o.ByteCount();
|
||||
}
|
||||
|
||||
// Helper to branch to fast path if possible
|
||||
void SerializeMessageDispatch(const ::google::protobuf::MessageLite& msg,
|
||||
void SerializeMessageDispatch(const MessageLite& msg,
|
||||
const FieldMetadata* field_table, int num_fields,
|
||||
int32 cached_size,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
const uint8* base = reinterpret_cast<const uint8*>(&msg);
|
||||
// Try the fast path
|
||||
uint8* ptr = output->GetDirectBufferForNBytesAndAdvance(cached_size);
|
||||
if (ptr) {
|
||||
// We use virtual dispatch to enable dedicated generated code for the
|
||||
// fast path.
|
||||
msg.InternalSerializeWithCachedSizesToArray(
|
||||
output->IsSerializationDeterministic(), ptr);
|
||||
return;
|
||||
}
|
||||
int32_t /*cached_size*/,
|
||||
io::CodedOutputStream* output) {
|
||||
const uint8_t* base = reinterpret_cast<const uint8_t*>(&msg);
|
||||
SerializeInternal(base, field_table, num_fields, output);
|
||||
}
|
||||
|
||||
// Helper to branch to fast path if possible
|
||||
void SerializeMessageDispatch(const ::google::protobuf::MessageLite& msg,
|
||||
void SerializeMessageDispatch(const MessageLite& msg,
|
||||
const FieldMetadata* field_table, int num_fields,
|
||||
int32 cached_size, ArrayOutput* output) {
|
||||
const uint8* base = reinterpret_cast<const uint8*>(&msg);
|
||||
int32_t /*cached_size*/, ArrayOutput* output) {
|
||||
const uint8_t* base = reinterpret_cast<const uint8_t*>(&msg);
|
||||
output->ptr = SerializeInternalToArray(base, field_table, num_fields,
|
||||
output->is_deterministic, output->ptr);
|
||||
}
|
||||
@@ -345,8 +345,9 @@ void SerializeMessageTo(const MessageLite* msg, const void* table_ptr,
|
||||
return;
|
||||
}
|
||||
const FieldMetadata* field_table = table->field_table;
|
||||
const uint8* base = reinterpret_cast<const uint8*>(msg);
|
||||
int cached_size = *reinterpret_cast<const int32*>(base + field_table->offset);
|
||||
const uint8_t* base = reinterpret_cast<const uint8_t*>(msg);
|
||||
int cached_size =
|
||||
*reinterpret_cast<const int32_t*>(base + field_table->offset);
|
||||
WriteLengthTo(cached_size, output);
|
||||
int num_fields = table->num_fields - 1;
|
||||
SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size,
|
||||
@@ -365,8 +366,9 @@ void SerializeGroupTo(const MessageLite* msg, const void* table_ptr,
|
||||
return;
|
||||
}
|
||||
const FieldMetadata* field_table = table->field_table;
|
||||
const uint8* base = reinterpret_cast<const uint8*>(msg);
|
||||
int cached_size = *reinterpret_cast<const int32*>(base + field_table->offset);
|
||||
const uint8_t* base = reinterpret_cast<const uint8_t*>(msg);
|
||||
int cached_size =
|
||||
*reinterpret_cast<const int32_t*>(base + field_table->offset);
|
||||
int num_fields = table->num_fields - 1;
|
||||
SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size,
|
||||
output);
|
||||
@@ -416,6 +418,15 @@ struct SingularFieldHelper<WireFormatLite::TYPE_MESSAGE> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SingularFieldHelper<FieldMetadata::kInlinedType> {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
WriteTagTo(md.tag, output);
|
||||
SerializeTo<FieldMetadata::kInlinedType>(&Get<std::string>(field), output);
|
||||
}
|
||||
};
|
||||
|
||||
template <int type>
|
||||
struct RepeatedFieldHelper {
|
||||
template <typename O>
|
||||
@@ -481,13 +492,17 @@ struct RepeatedFieldHelper<WireFormatLite::TYPE_MESSAGE> {
|
||||
for (int i = 0; i < AccessorHelper::Size(array); i++) {
|
||||
WriteTagTo(md.tag, output);
|
||||
SerializeMessageTo(
|
||||
static_cast<const MessageLite*>(AccessorHelper::Get(array, i)), md.ptr,
|
||||
output);
|
||||
static_cast<const MessageLite*>(AccessorHelper::Get(array, i)),
|
||||
md.ptr, output);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct RepeatedFieldHelper<FieldMetadata::kInlinedType>
|
||||
: RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {};
|
||||
|
||||
template <int type>
|
||||
struct PackedFieldHelper {
|
||||
template <typename O>
|
||||
@@ -497,7 +512,7 @@ struct PackedFieldHelper {
|
||||
if (array.empty()) return;
|
||||
WriteTagTo(md.tag, output);
|
||||
int cached_size =
|
||||
Get<int>(static_cast<const uint8*>(field) + sizeof(RepeatedField<T>));
|
||||
Get<int>(static_cast<const uint8_t*>(field) + sizeof(RepeatedField<T>));
|
||||
WriteLengthTo(cached_size, output);
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
SerializeTo<type>(&array[i], output);
|
||||
@@ -508,7 +523,8 @@ struct PackedFieldHelper {
|
||||
template <>
|
||||
struct PackedFieldHelper<WireFormatLite::TYPE_STRING> {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
static void Serialize(const void* /*field*/, const FieldMetadata& md,
|
||||
O* /*output*/) {
|
||||
GOOGLE_LOG(FATAL) << "Not implemented field number " << md.tag << " with type "
|
||||
<< md.type;
|
||||
}
|
||||
@@ -523,6 +539,9 @@ struct PackedFieldHelper<WireFormatLite::TYPE_GROUP>
|
||||
template <>
|
||||
struct PackedFieldHelper<WireFormatLite::TYPE_MESSAGE>
|
||||
: PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
|
||||
template <>
|
||||
struct PackedFieldHelper<FieldMetadata::kInlinedType>
|
||||
: PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
|
||||
|
||||
template <int type>
|
||||
struct OneOfFieldHelper {
|
||||
@@ -533,6 +552,15 @@ struct OneOfFieldHelper {
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct OneOfFieldHelper<FieldMetadata::kInlinedType> {
|
||||
template <typename O>
|
||||
static void Serialize(const void* field, const FieldMetadata& md, O* output) {
|
||||
SingularFieldHelper<FieldMetadata::kInlinedType>::Serialize(
|
||||
Get<const std::string*>(field), md, output);
|
||||
}
|
||||
};
|
||||
|
||||
void SerializeNotImplemented(int field) {
|
||||
GOOGLE_LOG(FATAL) << "Not implemented field number " << field;
|
||||
}
|
||||
@@ -564,15 +592,20 @@ bool IsNull<WireFormatLite::TYPE_BYTES>(const void* ptr) {
|
||||
|
||||
template <>
|
||||
bool IsNull<WireFormatLite::TYPE_GROUP>(const void* ptr) {
|
||||
return Get<const MessageLite*>(ptr) == NULL;
|
||||
return Get<const MessageLite*>(ptr) == nullptr;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool IsNull<WireFormatLite::TYPE_MESSAGE>(const void* ptr) {
|
||||
return Get<const MessageLite*>(ptr) == NULL;
|
||||
return Get<const MessageLite*>(ptr) == nullptr;
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
bool IsNull<FieldMetadata::kInlinedType>(const void* ptr) {
|
||||
return static_cast<const std::string*>(ptr)->empty();
|
||||
}
|
||||
|
||||
#define SERIALIZERS_FOR_TYPE(type) \
|
||||
case SERIALIZE_TABLE_OP(type, FieldMetadata::kPresence): \
|
||||
if (!IsPresent(base, field_metadata.has_offset)) continue; \
|
||||
@@ -594,13 +627,13 @@ bool IsNull<WireFormatLite::TYPE_MESSAGE>(const void* ptr) {
|
||||
OneOfFieldHelper<type>::Serialize(ptr, field_metadata, output); \
|
||||
break
|
||||
|
||||
void SerializeInternal(const uint8* base,
|
||||
void SerializeInternal(const uint8_t* base,
|
||||
const FieldMetadata* field_metadata_table,
|
||||
int32 num_fields,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
int32_t num_fields, io::CodedOutputStream* output) {
|
||||
SpecialSerializer func = nullptr;
|
||||
for (int i = 0; i < num_fields; i++) {
|
||||
const FieldMetadata& field_metadata = field_metadata_table[i];
|
||||
const uint8* ptr = base + field_metadata.offset;
|
||||
const uint8_t* ptr = base + field_metadata.offset;
|
||||
switch (field_metadata.type) {
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT);
|
||||
@@ -620,13 +653,14 @@ void SerializeInternal(const uint8* base,
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
|
||||
SERIALIZERS_FOR_TYPE(FieldMetadata::kInlinedType);
|
||||
|
||||
// Special cases
|
||||
case FieldMetadata::kSpecial:
|
||||
reinterpret_cast<SpecialSerializer>(
|
||||
const_cast<void*>(field_metadata.ptr))(
|
||||
base, field_metadata.offset, field_metadata.tag,
|
||||
field_metadata.has_offset, output);
|
||||
func = reinterpret_cast<SpecialSerializer>(
|
||||
const_cast<void*>(field_metadata.ptr));
|
||||
func(base, field_metadata.offset, field_metadata.tag,
|
||||
field_metadata.has_offset, output);
|
||||
break;
|
||||
default:
|
||||
// __builtin_unreachable()
|
||||
@@ -635,15 +669,16 @@ void SerializeInternal(const uint8* base,
|
||||
}
|
||||
}
|
||||
|
||||
uint8* SerializeInternalToArray(const uint8* base,
|
||||
const FieldMetadata* field_metadata_table,
|
||||
int32 num_fields, bool is_deterministic,
|
||||
uint8* buffer) {
|
||||
uint8_t* SerializeInternalToArray(const uint8_t* base,
|
||||
const FieldMetadata* field_metadata_table,
|
||||
int32_t num_fields, bool is_deterministic,
|
||||
uint8_t* buffer) {
|
||||
ArrayOutput array_output = {buffer, is_deterministic};
|
||||
ArrayOutput* output = &array_output;
|
||||
SpecialSerializer func = nullptr;
|
||||
for (int i = 0; i < num_fields; i++) {
|
||||
const FieldMetadata& field_metadata = field_metadata_table[i];
|
||||
const uint8* ptr = base + field_metadata.offset;
|
||||
const uint8_t* ptr = base + field_metadata.offset;
|
||||
switch (field_metadata.type) {
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT);
|
||||
@@ -663,16 +698,17 @@ uint8* SerializeInternalToArray(const uint8* base,
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
|
||||
SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
|
||||
SERIALIZERS_FOR_TYPE(FieldMetadata::kInlinedType);
|
||||
// Special cases
|
||||
case FieldMetadata::kSpecial: {
|
||||
io::ArrayOutputStream array_stream(array_output.ptr, INT_MAX);
|
||||
io::CodedOutputStream output(&array_stream);
|
||||
output.SetSerializationDeterministic(is_deterministic);
|
||||
reinterpret_cast<SpecialSerializer>(
|
||||
const_cast<void*>(field_metadata.ptr))(
|
||||
base, field_metadata.offset, field_metadata.tag,
|
||||
field_metadata.has_offset, &output);
|
||||
array_output.ptr += output.ByteCount();
|
||||
io::CodedOutputStream output_stream(&array_stream);
|
||||
output_stream.SetSerializationDeterministic(is_deterministic);
|
||||
func = reinterpret_cast<SpecialSerializer>(
|
||||
const_cast<void*>(field_metadata.ptr));
|
||||
func(base, field_metadata.offset, field_metadata.tag,
|
||||
field_metadata.has_offset, &output_stream);
|
||||
array_output.ptr += output_stream.ByteCount();
|
||||
} break;
|
||||
default:
|
||||
// __builtin_unreachable()
|
||||
@@ -683,39 +719,50 @@ uint8* SerializeInternalToArray(const uint8* base,
|
||||
}
|
||||
#undef SERIALIZERS_FOR_TYPE
|
||||
|
||||
void ExtensionSerializer(const uint8* ptr, uint32 offset, uint32 tag,
|
||||
uint32 has_offset,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
void ExtensionSerializer(const MessageLite* extendee, const uint8_t* ptr,
|
||||
uint32_t offset, uint32_t tag, uint32_t has_offset,
|
||||
io::CodedOutputStream* output) {
|
||||
reinterpret_cast<const ExtensionSet*>(ptr + offset)
|
||||
->SerializeWithCachedSizes(tag, has_offset, output);
|
||||
->SerializeWithCachedSizes(extendee, tag, has_offset, output);
|
||||
}
|
||||
|
||||
void UnknownFieldSerializerLite(const uint8* ptr, uint32 offset, uint32 tag,
|
||||
uint32 has_offset,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
void UnknownFieldSerializerLite(const uint8_t* ptr, uint32_t offset,
|
||||
uint32_t /*tag*/, uint32_t /*has_offset*/,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteString(
|
||||
reinterpret_cast<const InternalMetadataWithArenaLite*>(ptr + offset)
|
||||
->unknown_fields());
|
||||
reinterpret_cast<const InternalMetadata*>(ptr + offset)
|
||||
->unknown_fields<std::string>(&internal::GetEmptyString));
|
||||
}
|
||||
|
||||
MessageLite* DuplicateIfNonNullInternal(MessageLite* message, Arena* arena) {
|
||||
MessageLite* DuplicateIfNonNullInternal(MessageLite* message) {
|
||||
if (message) {
|
||||
MessageLite* ret = message->New(arena);
|
||||
MessageLite* ret = message->New();
|
||||
ret->CheckTypeAndMergeFrom(*message);
|
||||
return ret;
|
||||
} else {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GenericSwap(MessageLite* m1, MessageLite* m2) {
|
||||
std::unique_ptr<MessageLite> tmp(m1->New());
|
||||
tmp->CheckTypeAndMergeFrom(*m1);
|
||||
m1->Clear();
|
||||
m1->CheckTypeAndMergeFrom(*m2);
|
||||
m2->Clear();
|
||||
m2->CheckTypeAndMergeFrom(*tmp);
|
||||
}
|
||||
|
||||
// Returns a message owned by this Arena. This may require Own()ing or
|
||||
// duplicating the message.
|
||||
MessageLite* GetOwnedMessageInternal(Arena* message_arena,
|
||||
MessageLite* submessage,
|
||||
Arena* submessage_arena) {
|
||||
GOOGLE_DCHECK(submessage->GetArena() == submessage_arena);
|
||||
GOOGLE_DCHECK(Arena::InternalHelper<MessageLite>::GetOwningArena(submessage) ==
|
||||
submessage_arena);
|
||||
GOOGLE_DCHECK(message_arena != submessage_arena);
|
||||
if (message_arena != NULL && submessage_arena == NULL) {
|
||||
GOOGLE_DCHECK_EQ(submessage_arena, nullptr);
|
||||
if (message_arena != nullptr && submessage_arena == nullptr) {
|
||||
message_arena->Own(submessage);
|
||||
return submessage;
|
||||
} else {
|
||||
@@ -728,3 +775,5 @@ MessageLite* GetOwnedMessageInternal(Arena* message_arena,
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
+111
-218
@@ -39,73 +39,69 @@
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <climits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/any.h>
|
||||
#include <google/protobuf/has_bits.h>
|
||||
#include <google/protobuf/map_entry_lite.h>
|
||||
#include <google/protobuf/implicit_weak_message.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/stubs/once.h> // Add direct dep on port for pb.cc
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/stubs/casts.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
|
||||
class Arena;
|
||||
class Message;
|
||||
|
||||
namespace io { class CodedInputStream; }
|
||||
namespace io {
|
||||
class CodedInputStream;
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
|
||||
// Annotation for the compiler to emit a deprecation message if a field marked
|
||||
// with option 'deprecated=true' is used in the code, or for other things in
|
||||
// generated code which are deprecated.
|
||||
//
|
||||
// For internal use in the pb.cc files, deprecation warnings are suppressed
|
||||
// there.
|
||||
#undef DEPRECATED_PROTOBUF_FIELD
|
||||
#define PROTOBUF_DEPRECATED
|
||||
|
||||
#define GOOGLE_PROTOBUF_DEPRECATED_ATTR
|
||||
template <typename To, typename From>
|
||||
inline To DownCast(From* f) {
|
||||
return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f);
|
||||
}
|
||||
template <typename To, typename From>
|
||||
inline To DownCast(From& f) {
|
||||
return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f);
|
||||
}
|
||||
|
||||
|
||||
// Returns the offset of the given field within the given aggregate type.
|
||||
// This is equivalent to the ANSI C offsetof() macro. However, according
|
||||
// to the C++ standard, offsetof() only works on POD types, and GCC
|
||||
// enforces this requirement with a warning. In practice, this rule is
|
||||
// unnecessarily strict; there is probably no compiler or platform on
|
||||
// which the offsets of the direct fields of a class are non-constant.
|
||||
// Fields inherited from superclasses *can* have non-constant offsets,
|
||||
// but that's not what this macro will be used for.
|
||||
#if defined(__clang__)
|
||||
// For Clang we use __builtin_offsetof() and suppress the warning,
|
||||
// to avoid Control Flow Integrity and UBSan vptr sanitizers from
|
||||
// crashing while trying to validate the invalid reinterpet_casts.
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD) \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
|
||||
__builtin_offsetof(TYPE, FIELD) \
|
||||
_Pragma("clang diagnostic pop")
|
||||
#else
|
||||
// Note that we calculate relative to the pointer value 16 here since if we
|
||||
// just use zero, GCC complains about dereferencing a NULL pointer. We
|
||||
// choose 16 rather than some other number just in case the compiler would
|
||||
// be confused by an unaligned pointer.
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD) \
|
||||
static_cast< ::google::protobuf::uint32>( \
|
||||
reinterpret_cast<const char*>( \
|
||||
&reinterpret_cast<const TYPE*>(16)->FIELD) - \
|
||||
reinterpret_cast<const char*>(16))
|
||||
#endif
|
||||
// This fastpath inlines a single branch instead of having to make the
|
||||
// InitProtobufDefaults function call.
|
||||
// It also generates less inlined code than a function-scope static initializer.
|
||||
PROTOBUF_EXPORT extern std::atomic<bool> init_protobuf_defaults_state;
|
||||
PROTOBUF_EXPORT void InitProtobufDefaultsSlow();
|
||||
PROTOBUF_EXPORT inline void InitProtobufDefaults() {
|
||||
if (PROTOBUF_PREDICT_FALSE(
|
||||
!init_protobuf_defaults_state.load(std::memory_order_acquire))) {
|
||||
InitProtobufDefaultsSlow();
|
||||
}
|
||||
}
|
||||
|
||||
// Constants for special floating point values.
|
||||
LIBPROTOBUF_EXPORT double Infinity();
|
||||
LIBPROTOBUF_EXPORT double NaN();
|
||||
// This used by proto1
|
||||
PROTOBUF_EXPORT inline const std::string& GetEmptyString() {
|
||||
InitProtobufDefaults();
|
||||
return GetEmptyStringAlreadyInited();
|
||||
}
|
||||
|
||||
|
||||
// True if IsInitialized() is true for all elements of t. Type is expected
|
||||
@@ -113,178 +109,67 @@ LIBPROTOBUF_EXPORT double NaN();
|
||||
// helper here to keep the protobuf compiler from ever having to emit loops in
|
||||
// IsInitialized() methods. We want the C++ compiler to inline this or not
|
||||
// as it sees fit.
|
||||
template <class Type> bool AllAreInitialized(const Type& t) {
|
||||
for (int i = t.size(); --i >= 0; ) {
|
||||
template <typename Msg>
|
||||
bool AllAreInitialized(const RepeatedPtrField<Msg>& t) {
|
||||
for (int i = t.size(); --i >= 0;) {
|
||||
if (!t.Get(i).IsInitialized()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
LIBPROTOBUF_EXPORT void InitProtobufDefaults();
|
||||
|
||||
struct LIBPROTOBUF_EXPORT FieldMetadata {
|
||||
uint32 offset; // offset of this field in the struct
|
||||
uint32 tag; // field * 8 + wire_type
|
||||
// byte offset * 8 + bit_offset;
|
||||
// if the high bit is set then this is the byte offset of the oneof_case
|
||||
// for this field.
|
||||
uint32 has_offset;
|
||||
uint32 type; // the type of this field.
|
||||
const void* ptr; // auxiliary data
|
||||
|
||||
// From the serializer point of view each fundamental type can occur in
|
||||
// 4 different ways. For simplicity we treat all combinations as a cartesion
|
||||
// product although not all combinations are allowed.
|
||||
enum FieldTypeClass {
|
||||
kPresence,
|
||||
kNoPresence,
|
||||
kRepeated,
|
||||
kPacked,
|
||||
kOneOf,
|
||||
kNumTypeClasses // must be last enum
|
||||
};
|
||||
// C++ protobuf has 20 fundamental types, were we added Cord and StringPiece
|
||||
// and also distinquish the same types if they have different wire format.
|
||||
enum {
|
||||
kCordType = 19,
|
||||
kStringPieceType = 20,
|
||||
kNumTypes = 20,
|
||||
kSpecial = kNumTypes * kNumTypeClasses,
|
||||
};
|
||||
|
||||
static int CalculateType(int fundamental_type, FieldTypeClass type_class);
|
||||
};
|
||||
|
||||
inline bool IsPresent(const void* base, uint32 hasbit) {
|
||||
const uint32* has_bits_array = static_cast<const uint32*>(base);
|
||||
return has_bits_array[hasbit / 32] & (1u << (hasbit & 31));
|
||||
// "Weak" variant of AllAreInitialized, used to implement implicit weak fields.
|
||||
// This version operates on MessageLite to avoid introducing a dependency on the
|
||||
// concrete message type.
|
||||
template <class T>
|
||||
bool AllAreInitializedWeak(const RepeatedPtrField<T>& t) {
|
||||
for (int i = t.size(); --i >= 0;) {
|
||||
if (!reinterpret_cast<const RepeatedPtrFieldBase&>(t)
|
||||
.Get<ImplicitWeakTypeHandler<T> >(i)
|
||||
.IsInitialized()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool IsOneofPresent(const void* base, uint32 offset, uint32 tag) {
|
||||
const uint32* oneof =
|
||||
reinterpret_cast<const uint32*>(static_cast<const uint8*>(base) + offset);
|
||||
inline bool IsPresent(const void* base, uint32_t hasbit) {
|
||||
const uint32_t* has_bits_array = static_cast<const uint32_t*>(base);
|
||||
return (has_bits_array[hasbit / 32] & (1u << (hasbit & 31))) != 0;
|
||||
}
|
||||
|
||||
inline bool IsOneofPresent(const void* base, uint32_t offset, uint32_t tag) {
|
||||
const uint32_t* oneof = reinterpret_cast<const uint32_t*>(
|
||||
static_cast<const uint8_t*>(base) + offset);
|
||||
return *oneof == tag >> 3;
|
||||
}
|
||||
|
||||
typedef void (*SpecialSerializer)(const uint8* base, uint32 offset, uint32 tag,
|
||||
uint32 has_offset,
|
||||
::google::protobuf::io::CodedOutputStream* output);
|
||||
typedef void (*SpecialSerializer)(const uint8_t* base, uint32_t offset,
|
||||
uint32_t tag, uint32_t has_offset,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
LIBPROTOBUF_EXPORT void ExtensionSerializer(const uint8* base, uint32 offset, uint32 tag,
|
||||
uint32 has_offset,
|
||||
::google::protobuf::io::CodedOutputStream* output);
|
||||
LIBPROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8* base, uint32 offset, uint32 tag,
|
||||
uint32 has_offset,
|
||||
::google::protobuf::io::CodedOutputStream* output);
|
||||
PROTOBUF_EXPORT void ExtensionSerializer(const MessageLite* extendee,
|
||||
const uint8_t* ptr, uint32_t offset,
|
||||
uint32_t tag, uint32_t has_offset,
|
||||
io::CodedOutputStream* output);
|
||||
PROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8_t* base,
|
||||
uint32_t offset, uint32_t tag,
|
||||
uint32_t has_offset,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
struct SerializationTable {
|
||||
int num_fields;
|
||||
const FieldMetadata* field_table;
|
||||
};
|
||||
|
||||
LIBPROTOBUF_EXPORT void SerializeInternal(const uint8* base, const FieldMetadata* table,
|
||||
int num_fields, ::google::protobuf::io::CodedOutputStream* output);
|
||||
|
||||
inline void TableSerialize(const ::google::protobuf::MessageLite& msg,
|
||||
const SerializationTable* table,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
const FieldMetadata* field_table = table->field_table;
|
||||
int num_fields = table->num_fields - 1;
|
||||
const uint8* base = reinterpret_cast<const uint8*>(&msg);
|
||||
// TODO(gerbens) This skips the first test if we could use the fast
|
||||
// array serialization path, we should make this
|
||||
// int cached_size =
|
||||
// *reinterpret_cast<const int32*>(base + field_table->offset);
|
||||
// SerializeWithCachedSize(msg, field_table + 1, num_fields, cached_size, ...)
|
||||
// But we keep conformance with the old way for now.
|
||||
SerializeInternal(base, field_table + 1, num_fields, output);
|
||||
}
|
||||
|
||||
uint8* SerializeInternalToArray(const uint8* base, const FieldMetadata* table,
|
||||
int num_fields, bool is_deterministic,
|
||||
uint8* buffer);
|
||||
|
||||
inline uint8* TableSerializeToArray(const ::google::protobuf::MessageLite& msg,
|
||||
const SerializationTable* table,
|
||||
bool is_deterministic, uint8* buffer) {
|
||||
const uint8* base = reinterpret_cast<const uint8*>(&msg);
|
||||
const FieldMetadata* field_table = table->field_table + 1;
|
||||
int num_fields = table->num_fields - 1;
|
||||
return SerializeInternalToArray(base, field_table, num_fields,
|
||||
is_deterministic, buffer);
|
||||
}
|
||||
PROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message);
|
||||
PROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena,
|
||||
MessageLite* submessage,
|
||||
Arena* submessage_arena);
|
||||
PROTOBUF_EXPORT void GenericSwap(MessageLite* m1, MessageLite* m2);
|
||||
// We specialize GenericSwap for non-lite messages to benefit from reflection.
|
||||
PROTOBUF_EXPORT void GenericSwap(Message* m1, Message* m2);
|
||||
|
||||
template <typename T>
|
||||
struct CompareHelper {
|
||||
bool operator()(const T& a, const T& b) { return a < b; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct CompareHelper<ArenaStringPtr> {
|
||||
bool operator()(const ArenaStringPtr& a, const ArenaStringPtr& b) {
|
||||
return a.Get() < b.Get();
|
||||
}
|
||||
};
|
||||
|
||||
struct CompareMapKey {
|
||||
template <typename T>
|
||||
bool operator()(const MapEntryHelper<T>& a, const MapEntryHelper<T>& b) {
|
||||
return Compare(a.key_, b.key_);
|
||||
}
|
||||
template <typename T>
|
||||
bool Compare(const T& a, const T& b) {
|
||||
return CompareHelper<T>()(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename MapFieldType, const SerializationTable* table>
|
||||
void MapFieldSerializer(const uint8* base, uint32 offset, uint32 tag,
|
||||
uint32 has_offset,
|
||||
::google::protobuf::io::CodedOutputStream* output) {
|
||||
typedef MapEntryHelper<typename MapFieldType::EntryTypeTrait> Entry;
|
||||
typedef typename MapFieldType::MapType::const_iterator Iter;
|
||||
|
||||
const MapFieldType& map_field =
|
||||
*reinterpret_cast<const MapFieldType*>(base + offset);
|
||||
const SerializationTable* t =
|
||||
table +
|
||||
has_offset; // has_offset is overloaded for maps to mean table offset
|
||||
if (!output->IsSerializationDeterministic()) {
|
||||
for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
|
||||
++it) {
|
||||
Entry map_entry(*it);
|
||||
output->WriteVarint32(tag);
|
||||
output->WriteVarint32(map_entry._cached_size_);
|
||||
SerializeInternal(reinterpret_cast<const uint8*>(&map_entry),
|
||||
t->field_table, t->num_fields, output);
|
||||
}
|
||||
} else {
|
||||
std::vector<Entry> v;
|
||||
for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
|
||||
++it) {
|
||||
v.push_back(Entry(*it));
|
||||
}
|
||||
std::sort(v.begin(), v.end(), CompareMapKey());
|
||||
for (int i = 0; i < v.size(); i++) {
|
||||
output->WriteVarint32(tag);
|
||||
output->WriteVarint32(v[i]._cached_size_);
|
||||
SerializeInternal(reinterpret_cast<const uint8*>(&v[i]), t->field_table,
|
||||
t->num_fields, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LIBPROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message, Arena* arena);
|
||||
LIBPROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena,
|
||||
MessageLite* submessage,
|
||||
Arena* submessage_arena);
|
||||
|
||||
template <typename T>
|
||||
T* DuplicateIfNonNull(T* message, Arena* arena) {
|
||||
T* DuplicateIfNonNull(T* message) {
|
||||
// The casts must be reinterpret_cast<> because T might be a forward-declared
|
||||
// type that the compiler doesn't know is related to MessageLite.
|
||||
return reinterpret_cast<T*>(DuplicateIfNonNullInternal(
|
||||
reinterpret_cast<MessageLite*>(message), arena));
|
||||
return reinterpret_cast<T*>(
|
||||
DuplicateIfNonNullInternal(reinterpret_cast<MessageLite*>(message)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -297,24 +182,32 @@ T* GetOwnedMessage(Arena* message_arena, T* submessage,
|
||||
submessage_arena));
|
||||
}
|
||||
|
||||
// Returns a message owned by this Arena. This may require Own()ing or
|
||||
// duplicating the message.
|
||||
template <typename T>
|
||||
T* GetOwnedMessage(T* message, Arena* arena) {
|
||||
GOOGLE_DCHECK(message);
|
||||
Arena* message_arena = google::protobuf::Arena::GetArena(message);
|
||||
if (message_arena == arena) {
|
||||
return message;
|
||||
} else if (arena != NULL && message_arena == NULL) {
|
||||
arena->Own(message);
|
||||
return message;
|
||||
} else {
|
||||
return DuplicateIfNonNull(message, arena);
|
||||
}
|
||||
// Hide atomic from the public header and allow easy change to regular int
|
||||
// on platforms where the atomic might have a perf impact.
|
||||
class PROTOBUF_EXPORT CachedSize {
|
||||
public:
|
||||
int Get() const { return size_.load(std::memory_order_relaxed); }
|
||||
void Set(int size) { size_.store(size, std::memory_order_relaxed); }
|
||||
|
||||
private:
|
||||
std::atomic<int> size_{0};
|
||||
};
|
||||
|
||||
PROTOBUF_EXPORT void DestroyMessage(const void* message);
|
||||
PROTOBUF_EXPORT void DestroyString(const void* s);
|
||||
// Destroy (not delete) the message
|
||||
inline void OnShutdownDestroyMessage(const void* ptr) {
|
||||
OnShutdownRun(DestroyMessage, ptr);
|
||||
}
|
||||
// Destroy the string (call std::string destructor)
|
||||
inline void OnShutdownDestroyString(const std::string* ptr) {
|
||||
OnShutdownRun(DestroyString, ptr);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
|
||||
+20
-9
@@ -32,27 +32,32 @@
|
||||
#define GOOGLE_PROTOBUF_HAS_BITS_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/port.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
template<size_t doublewords>
|
||||
template <size_t doublewords>
|
||||
class HasBits {
|
||||
public:
|
||||
HasBits() GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE { Clear(); }
|
||||
PROTOBUF_NDEBUG_INLINE constexpr HasBits() : has_bits_{} {}
|
||||
|
||||
void Clear() GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
PROTOBUF_NDEBUG_INLINE void Clear() {
|
||||
memset(has_bits_, 0, sizeof(has_bits_));
|
||||
}
|
||||
|
||||
::google::protobuf::uint32& operator[](int index) GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
PROTOBUF_NDEBUG_INLINE uint32_t& operator[](int index) {
|
||||
return has_bits_[index];
|
||||
}
|
||||
|
||||
const ::google::protobuf::uint32& operator[](int index) const
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE {
|
||||
PROTOBUF_NDEBUG_INLINE const uint32_t& operator[](int index) const {
|
||||
return has_bits_[index];
|
||||
}
|
||||
|
||||
@@ -64,10 +69,14 @@ class HasBits {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
void Or(const HasBits<doublewords>& rhs) {
|
||||
for (size_t i = 0; i < doublewords; i++) has_bits_[i] |= rhs[i];
|
||||
}
|
||||
|
||||
bool empty() const;
|
||||
|
||||
private:
|
||||
::google::protobuf::uint32 has_bits_[doublewords];
|
||||
uint32_t has_bits_[doublewords];
|
||||
};
|
||||
|
||||
template <>
|
||||
@@ -100,6 +109,8 @@ inline bool HasBits<doublewords>::empty() const {
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_HAS_BITS_H__
|
||||
|
||||
+27
-6
@@ -28,19 +28,40 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/stubs/statusor.h>
|
||||
#include <google/protobuf/implicit_weak_message.h>
|
||||
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace util {
|
||||
namespace internal {
|
||||
|
||||
void StatusOrHelper::Crash(const Status& status) {
|
||||
GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error "
|
||||
<< status.ToString();
|
||||
const char* ImplicitWeakMessage::_InternalParse(const char* ptr,
|
||||
ParseContext* ctx) {
|
||||
return ctx->AppendString(ptr, &data_);
|
||||
}
|
||||
|
||||
ExplicitlyConstructed<ImplicitWeakMessage>
|
||||
implicit_weak_message_default_instance;
|
||||
internal::once_flag implicit_weak_message_once_init_;
|
||||
|
||||
void InitImplicitWeakMessageDefaultInstance() {
|
||||
implicit_weak_message_default_instance.DefaultConstruct();
|
||||
}
|
||||
|
||||
const ImplicitWeakMessage* ImplicitWeakMessage::default_instance() {
|
||||
internal::call_once(implicit_weak_message_once_init_,
|
||||
InitImplicitWeakMessageDefaultInstance);
|
||||
return &implicit_weak_message_default_instance.get();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace util
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
@@ -0,0 +1,186 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__
|
||||
#define GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
// This file is logically internal-only and should only be used by protobuf
|
||||
// generated code.
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// An implementation of MessageLite that treats all data as unknown. This type
|
||||
// acts as a placeholder for an implicit weak field in the case where the true
|
||||
// message type does not get linked into the binary.
|
||||
class PROTOBUF_EXPORT ImplicitWeakMessage : public MessageLite {
|
||||
public:
|
||||
ImplicitWeakMessage() {}
|
||||
explicit ImplicitWeakMessage(Arena* arena) : MessageLite(arena) {}
|
||||
|
||||
static const ImplicitWeakMessage* default_instance();
|
||||
|
||||
std::string GetTypeName() const override { return ""; }
|
||||
|
||||
MessageLite* New(Arena* arena) const override {
|
||||
return Arena::CreateMessage<ImplicitWeakMessage>(arena);
|
||||
}
|
||||
|
||||
void Clear() override { data_.clear(); }
|
||||
|
||||
bool IsInitialized() const override { return true; }
|
||||
|
||||
void CheckTypeAndMergeFrom(const MessageLite& other) override {
|
||||
data_.append(static_cast<const ImplicitWeakMessage&>(other).data_);
|
||||
}
|
||||
|
||||
const char* _InternalParse(const char* ptr, ParseContext* ctx) final;
|
||||
|
||||
size_t ByteSizeLong() const override { return data_.size(); }
|
||||
|
||||
uint8_t* _InternalSerialize(uint8_t* target,
|
||||
io::EpsCopyOutputStream* stream) const final {
|
||||
return stream->WriteRaw(data_.data(), static_cast<int>(data_.size()),
|
||||
target);
|
||||
}
|
||||
|
||||
int GetCachedSize() const override { return static_cast<int>(data_.size()); }
|
||||
|
||||
typedef void InternalArenaConstructable_;
|
||||
|
||||
private:
|
||||
std::string data_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImplicitWeakMessage);
|
||||
};
|
||||
|
||||
// A type handler for use with implicit weak repeated message fields.
|
||||
template <typename ImplicitWeakType>
|
||||
class ImplicitWeakTypeHandler {
|
||||
public:
|
||||
typedef MessageLite Type;
|
||||
static constexpr bool Moveable = false;
|
||||
|
||||
static inline MessageLite* NewFromPrototype(const MessageLite* prototype,
|
||||
Arena* arena = nullptr) {
|
||||
return prototype->New(arena);
|
||||
}
|
||||
|
||||
static inline void Delete(MessageLite* value, Arena* arena) {
|
||||
if (arena == nullptr) {
|
||||
delete value;
|
||||
}
|
||||
}
|
||||
static inline Arena* GetArena(MessageLite* value) {
|
||||
return value->GetArena();
|
||||
}
|
||||
static inline void Clear(MessageLite* value) { value->Clear(); }
|
||||
static void Merge(const MessageLite& from, MessageLite* to) {
|
||||
to->CheckTypeAndMergeFrom(from);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename T>
|
||||
struct WeakRepeatedPtrField {
|
||||
using TypeHandler = internal::ImplicitWeakTypeHandler<T>;
|
||||
constexpr WeakRepeatedPtrField() : weak() {}
|
||||
explicit WeakRepeatedPtrField(Arena* arena) : weak(arena) {}
|
||||
~WeakRepeatedPtrField() { weak.template Destroy<TypeHandler>(); }
|
||||
|
||||
typedef internal::RepeatedPtrIterator<MessageLite> iterator;
|
||||
typedef internal::RepeatedPtrIterator<const MessageLite> const_iterator;
|
||||
typedef internal::RepeatedPtrOverPtrsIterator<MessageLite*, void*>
|
||||
pointer_iterator;
|
||||
typedef internal::RepeatedPtrOverPtrsIterator<const MessageLite* const,
|
||||
const void* const>
|
||||
const_pointer_iterator;
|
||||
|
||||
iterator begin() { return iterator(base().raw_data()); }
|
||||
const_iterator begin() const { return iterator(base().raw_data()); }
|
||||
const_iterator cbegin() const { return begin(); }
|
||||
iterator end() { return begin() + base().size(); }
|
||||
const_iterator end() const { return begin() + base().size(); }
|
||||
const_iterator cend() const { return end(); }
|
||||
pointer_iterator pointer_begin() {
|
||||
return pointer_iterator(base().raw_mutable_data());
|
||||
}
|
||||
const_pointer_iterator pointer_begin() const {
|
||||
return const_pointer_iterator(base().raw_mutable_data());
|
||||
}
|
||||
pointer_iterator pointer_end() {
|
||||
return pointer_iterator(base().raw_mutable_data() + base().size());
|
||||
}
|
||||
const_pointer_iterator pointer_end() const {
|
||||
return const_pointer_iterator(base().raw_mutable_data() + base().size());
|
||||
}
|
||||
|
||||
MessageLite* AddWeak(const MessageLite* prototype) {
|
||||
return base().AddWeak(prototype);
|
||||
}
|
||||
T* Add() { return weak.Add(); }
|
||||
void Clear() { base().template Clear<TypeHandler>(); }
|
||||
void MergeFrom(const WeakRepeatedPtrField& other) {
|
||||
base().template MergeFrom<TypeHandler>(other.base());
|
||||
}
|
||||
void InternalSwap(WeakRepeatedPtrField* other) {
|
||||
base().InternalSwap(&other->base());
|
||||
}
|
||||
|
||||
const internal::RepeatedPtrFieldBase& base() const { return weak; }
|
||||
internal::RepeatedPtrFieldBase& base() { return weak; }
|
||||
// Union disables running the destructor. Which would create a strong link.
|
||||
// Instead we explicitly destroy the underlying base through the virtual
|
||||
// destructor.
|
||||
union {
|
||||
RepeatedPtrField<T> weak;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__
|
||||
@@ -0,0 +1,384 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Arena;
|
||||
|
||||
namespace internal {
|
||||
|
||||
// InlinedStringField wraps a std::string instance and exposes an API similar to
|
||||
// ArenaStringPtr's wrapping of a std::string* instance.
|
||||
//
|
||||
// default_value parameters are taken for consistency with ArenaStringPtr, but
|
||||
// are not used for most methods. With inlining, these should be removed from
|
||||
// the generated binary.
|
||||
//
|
||||
// InlinedStringField has a donating mechanism that allows string buffer
|
||||
// allocated on arena. A string is donated means both the string container and
|
||||
// the data buffer are on arena. The donating mechanism here is similar to the
|
||||
// one in ArenaStringPtr with some differences:
|
||||
//
|
||||
// When an InlinedStringField is constructed, the donating state is true. This
|
||||
// is because the string container is directly stored in the message on the
|
||||
// arena:
|
||||
//
|
||||
// Construction: donated=true
|
||||
// Arena:
|
||||
// +-----------------------+
|
||||
// |Message foo: |
|
||||
// | +-------------------+ |
|
||||
// | |InlinedStringField:| |
|
||||
// | | +-----+ | |
|
||||
// | | | | | | | |
|
||||
// | | +-----+ | |
|
||||
// | +-------------------+ |
|
||||
// +-----------------------+
|
||||
//
|
||||
// When lvalue Set is called, the donating state is still true. String data will
|
||||
// be allocated on the arena:
|
||||
//
|
||||
// Lvalue Set: donated=true
|
||||
// Arena:
|
||||
// +-----------------------+
|
||||
// |Message foo: |
|
||||
// | +-------------------+ |
|
||||
// | |InlinedStringField:| |
|
||||
// | | +-----+ | |
|
||||
// | | | | | | | |
|
||||
// | | +|----+ | |
|
||||
// | +--|----------------+ |
|
||||
// | V |
|
||||
// | +----------------+ |
|
||||
// | |'f','o','o',... | |
|
||||
// | +----------------+ |
|
||||
// +-----------------------+
|
||||
//
|
||||
// Some operations will undonate a donated string, including: Mutable,
|
||||
// SetAllocated, Rvalue Set, and Swap with a non-donated string.
|
||||
//
|
||||
// For more details of the donating states transitions, go/pd-inlined-string.
|
||||
class PROTOBUF_EXPORT InlinedStringField {
|
||||
public:
|
||||
InlinedStringField() { Init(); }
|
||||
inline void Init() { new (get_mutable()) std::string(); }
|
||||
// Add the dummy parameter just to make InlinedStringField(nullptr)
|
||||
// unambiguous.
|
||||
constexpr InlinedStringField(
|
||||
const ExplicitlyConstructed<std::string>* /*default_value*/,
|
||||
bool /*dummy*/)
|
||||
: value_{} {}
|
||||
explicit InlinedStringField(const std::string& default_value);
|
||||
explicit InlinedStringField(Arena* arena);
|
||||
~InlinedStringField() { Destruct(); }
|
||||
|
||||
// Lvalue Set. To save space, we pack the donating states of multiple
|
||||
// InlinedStringFields into an uint32_t `donating_states`. The `mask`
|
||||
// indicates the position of the bit for this InlinedStringField. `donated` is
|
||||
// whether this field is donated.
|
||||
//
|
||||
// The caller should guarantee that:
|
||||
//
|
||||
// `donated == ((donating_states & ~mask) != 0)`
|
||||
//
|
||||
// This method never changes the `donating_states`.
|
||||
void Set(const std::string* default_value, ConstStringParam value,
|
||||
Arena* arena, bool donated, uint32_t* /*donating_states*/,
|
||||
uint32_t /*mask*/) {
|
||||
(void)arena;
|
||||
(void)donated;
|
||||
SetNoArena(default_value, value);
|
||||
}
|
||||
|
||||
// Rvalue Set. If this field is donated, this method will undonate this field
|
||||
// by mutating the `donating_states` according to `mask`.
|
||||
void Set(const std::string* default_value, std::string&& value, Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask);
|
||||
|
||||
template <typename FirstParam>
|
||||
void Set(FirstParam p1, const char* str, ::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask) {
|
||||
Set(p1, ConstStringParam(str), arena, donated, donating_states, mask);
|
||||
}
|
||||
|
||||
template <typename FirstParam>
|
||||
void Set(FirstParam p1, const char* str, size_t size, ::google::protobuf::Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask) {
|
||||
ConstStringParam sp{str, size}; // for string_view and `const string &`
|
||||
Set(p1, sp, arena, donated, donating_states, mask);
|
||||
}
|
||||
|
||||
template <typename FirstParam, typename RefWrappedType>
|
||||
void Set(FirstParam p1,
|
||||
std::reference_wrapper<RefWrappedType> const_string_ref,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask) {
|
||||
Set(p1, const_string_ref.get(), arena, donated, donating_states, mask);
|
||||
}
|
||||
|
||||
template <typename FirstParam, typename SecondParam>
|
||||
void SetBytes(FirstParam p1, SecondParam&& p2, ::google::protobuf::Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask) {
|
||||
Set(p1, static_cast<SecondParam&&>(p2), arena, donated, donating_states,
|
||||
mask);
|
||||
}
|
||||
|
||||
template <typename FirstParam>
|
||||
void SetBytes(FirstParam p1, const void* str, size_t size,
|
||||
::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask) {
|
||||
// Must work whether ConstStringParam is string_view or `const string &`
|
||||
ConstStringParam sp{static_cast<const char*>(str), size};
|
||||
Set(p1, sp, arena, donated, donating_states, mask);
|
||||
}
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE void SetNoArena(const std::string* default_value,
|
||||
StringPiece value);
|
||||
PROTOBUF_NDEBUG_INLINE void SetNoArena(const std::string* default_value,
|
||||
std::string&& value);
|
||||
|
||||
// Basic accessors.
|
||||
PROTOBUF_NDEBUG_INLINE const std::string& Get() const { return GetNoArena(); }
|
||||
PROTOBUF_NDEBUG_INLINE const std::string& GetNoArena() const;
|
||||
|
||||
// Mutable returns a std::string* instance that is heap-allocated. If this
|
||||
// field is donated, this method undonates this field by mutating the
|
||||
// `donating_states` according to `mask`, and copies the content of the
|
||||
// original string to the returning string.
|
||||
std::string* Mutable(const LazyString& default_value, Arena* arena,
|
||||
bool donated, uint32_t* donating_states, uint32_t mask);
|
||||
std::string* Mutable(ArenaStringPtr::EmptyDefault, Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask);
|
||||
|
||||
// Release returns a std::string* instance that is heap-allocated and is not
|
||||
// Own()'d by any arena. If the field is not set, this returns nullptr. The
|
||||
// caller retains ownership. Clears this field back to nullptr state. Used to
|
||||
// implement release_<field>() methods on generated classes.
|
||||
PROTOBUF_NODISCARD std::string* Release(const std::string* default_value,
|
||||
Arena* arena, bool donated);
|
||||
PROTOBUF_NODISCARD std::string* ReleaseNonDefault(
|
||||
const std::string* default_value, Arena* arena);
|
||||
std::string* ReleaseNonDefaultNoArena(const std::string* default_value);
|
||||
|
||||
// Takes a std::string that is heap-allocated, and takes ownership. The
|
||||
// std::string's destructor is registered with the arena. Used to implement
|
||||
// set_allocated_<field> in generated classes.
|
||||
//
|
||||
// If this field is donated, this method undonates this field by mutating the
|
||||
// `donating_states` according to `mask`.
|
||||
void SetAllocated(const std::string* default_value, std::string* value,
|
||||
Arena* arena, bool donated, uint32_t* donating_states,
|
||||
uint32_t mask);
|
||||
|
||||
void SetAllocatedNoArena(const std::string* default_value,
|
||||
std::string* value);
|
||||
|
||||
// When one of `this` and `from` is donated and the other is not donated, this
|
||||
// method will undonate the donated one and swap the two heap-allocated
|
||||
// strings.
|
||||
PROTOBUF_NDEBUG_INLINE void Swap(InlinedStringField* from,
|
||||
const std::string* default_value,
|
||||
Arena* arena, bool donated,
|
||||
bool from_donated, uint32_t* donating_states,
|
||||
uint32_t* from_donating_states,
|
||||
uint32_t mask);
|
||||
|
||||
// Frees storage (if not on an arena).
|
||||
PROTOBUF_NDEBUG_INLINE void Destroy(const std::string* default_value,
|
||||
Arena* arena) {
|
||||
if (arena == nullptr) {
|
||||
DestroyNoArena(default_value);
|
||||
}
|
||||
}
|
||||
PROTOBUF_NDEBUG_INLINE void DestroyNoArena(const std::string* default_value);
|
||||
|
||||
// Clears content, but keeps allocated std::string, to avoid the overhead of
|
||||
// heap operations. After this returns, the content (as seen by the user) will
|
||||
// always be the empty std::string.
|
||||
PROTOBUF_NDEBUG_INLINE void ClearToEmpty() { ClearNonDefaultToEmpty(); }
|
||||
PROTOBUF_NDEBUG_INLINE void ClearNonDefaultToEmpty() {
|
||||
get_mutable()->clear();
|
||||
}
|
||||
|
||||
// Clears content, but keeps allocated std::string if arena != nullptr, to
|
||||
// avoid the overhead of heap operations. After this returns, the content (as
|
||||
// seen by the user) will always be equal to |default_value|.
|
||||
void ClearToDefault(const LazyString& default_value, Arena* arena,
|
||||
bool donated);
|
||||
|
||||
// Returns a mutable pointer, but doesn't initialize the string to the
|
||||
// default value.
|
||||
PROTOBUF_NDEBUG_INLINE std::string* MutableNoArenaNoDefault(
|
||||
const std::string* /*default_value*/);
|
||||
|
||||
// Generated code / reflection only! Returns a mutable pointer to the string.
|
||||
PROTOBUF_NDEBUG_INLINE std::string* UnsafeMutablePointer();
|
||||
|
||||
// InlinedStringField doesn't have things like the `default_value` pointer in
|
||||
// ArenaStringPtr.
|
||||
bool IsDefault(const std::string* /*default_value*/) const { return false; }
|
||||
|
||||
private:
|
||||
void Destruct() { get_mutable()->~basic_string(); }
|
||||
|
||||
PROTOBUF_NDEBUG_INLINE std::string* get_mutable();
|
||||
PROTOBUF_NDEBUG_INLINE const std::string* get_const() const;
|
||||
|
||||
alignas(std::string) char value_[sizeof(std::string)];
|
||||
|
||||
std::string* MutableSlow(::google::protobuf::Arena* arena, bool donated,
|
||||
uint32_t* donating_states, uint32_t mask);
|
||||
|
||||
|
||||
// When constructed in an Arena, we want our destructor to be skipped.
|
||||
friend class ::google::protobuf::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
};
|
||||
|
||||
inline std::string* InlinedStringField::get_mutable() {
|
||||
return reinterpret_cast<std::string*>(&value_);
|
||||
}
|
||||
|
||||
inline const std::string* InlinedStringField::get_const() const {
|
||||
return reinterpret_cast<const std::string*>(&value_);
|
||||
}
|
||||
|
||||
inline InlinedStringField::InlinedStringField(
|
||||
const std::string& default_value) {
|
||||
new (get_mutable()) std::string(default_value);
|
||||
}
|
||||
|
||||
inline InlinedStringField::InlinedStringField(Arena* arena) {
|
||||
Init();
|
||||
if (arena != nullptr) {
|
||||
arena->OwnDestructor(get_mutable());
|
||||
}
|
||||
}
|
||||
|
||||
inline const std::string& InlinedStringField::GetNoArena() const {
|
||||
return *get_const();
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetAllocatedNoArena(
|
||||
const std::string* /*default_value*/, std::string* value) {
|
||||
if (value == nullptr) {
|
||||
// Currently, inlined string field can't have non empty default.
|
||||
get_mutable()->clear();
|
||||
} else {
|
||||
get_mutable()->assign(std::move(*value));
|
||||
delete value;
|
||||
}
|
||||
}
|
||||
|
||||
inline void InlinedStringField::DestroyNoArena(const std::string*) {
|
||||
// This is invoked from the generated message's ArenaDtor, which is used to
|
||||
// clean up objects not allocated on the Arena.
|
||||
this->~InlinedStringField();
|
||||
}
|
||||
|
||||
inline std::string* InlinedStringField::ReleaseNonDefaultNoArena(
|
||||
const std::string* /*default_value*/) {
|
||||
// Currently, inlined string field can't have non empty default.
|
||||
auto* released = new std::string();
|
||||
get_mutable()->swap(*released);
|
||||
return released;
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetNoArena(const std::string* /*default_value*/,
|
||||
StringPiece value) {
|
||||
get_mutable()->assign(value.data(), value.length());
|
||||
}
|
||||
|
||||
inline void InlinedStringField::SetNoArena(const std::string* /*default_value*/,
|
||||
std::string&& value) {
|
||||
get_mutable()->assign(std::move(value));
|
||||
}
|
||||
|
||||
inline void InlinedStringField::Swap(
|
||||
InlinedStringField* from, const std::string* /*default_value*/,
|
||||
Arena* arena, bool donated, bool from_donated, uint32_t* donating_states,
|
||||
uint32_t* from_donating_states, uint32_t mask) {
|
||||
#if GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
|
||||
// If one is donated and the other is not, undonate the donated one.
|
||||
if (donated && !from_donated) {
|
||||
MutableSlow(arena, donated, donating_states, mask);
|
||||
} else if (!donated && from_donated) {
|
||||
from->MutableSlow(arena, from_donated, from_donating_states, mask);
|
||||
}
|
||||
// Then, swap the two undonated strings.
|
||||
#else
|
||||
(void)arena;
|
||||
(void)donated;
|
||||
(void)from_donated;
|
||||
(void)donating_states;
|
||||
(void)from_donating_states;
|
||||
(void)mask;
|
||||
#endif
|
||||
get_mutable()->swap(*from->get_mutable());
|
||||
}
|
||||
|
||||
inline std::string* InlinedStringField::MutableNoArenaNoDefault(
|
||||
const std::string*) {
|
||||
return get_mutable();
|
||||
}
|
||||
|
||||
inline std::string* InlinedStringField::UnsafeMutablePointer() {
|
||||
return get_mutable();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
|
||||
+460
-273
@@ -38,17 +38,24 @@
|
||||
// will not cross the end of the buffer, since we can avoid a lot
|
||||
// of branching in this case.
|
||||
|
||||
#include <google/protobuf/io/coded_stream_inl.h>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
@@ -59,8 +66,8 @@ static const int kMaxVarintBytes = 10;
|
||||
static const int kMaxVarint32Bytes = 5;
|
||||
|
||||
|
||||
inline bool NextNonEmpty(ZeroCopyInputStream* input,
|
||||
const void** data, int* size) {
|
||||
inline bool NextNonEmpty(ZeroCopyInputStream* input, const void** data,
|
||||
int* size) {
|
||||
bool success;
|
||||
do {
|
||||
success = input->Next(data, size);
|
||||
@@ -82,10 +89,6 @@ CodedInputStream::~CodedInputStream() {
|
||||
int CodedInputStream::default_recursion_limit_ = 100;
|
||||
|
||||
|
||||
void CodedOutputStream::EnableAliasing(bool enabled) {
|
||||
aliasing_enabled_ = enabled && output_->AllowsAliasing();
|
||||
}
|
||||
|
||||
void CodedInputStream::BackUpInputToCurrentPosition() {
|
||||
int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_;
|
||||
if (backup_bytes > 0) {
|
||||
@@ -121,9 +124,9 @@ CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
|
||||
// security: byte_limit is possibly evil, so check for negative values
|
||||
// and overflow. Also check that the new requested limit is before the
|
||||
// previous limit; otherwise we continue to enforce the previous limit.
|
||||
if GOOGLE_PREDICT_TRUE(byte_limit >= 0 &&
|
||||
byte_limit <= INT_MAX - current_position &&
|
||||
byte_limit < current_limit_ - current_position) {
|
||||
if (PROTOBUF_PREDICT_TRUE(byte_limit >= 0 &&
|
||||
byte_limit <= INT_MAX - current_position &&
|
||||
byte_limit < current_limit_ - current_position)) {
|
||||
current_limit_ = current_position + byte_limit;
|
||||
RecomputeBufferLimits();
|
||||
}
|
||||
@@ -148,7 +151,7 @@ CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) {
|
||||
}
|
||||
|
||||
CodedInputStream::Limit CodedInputStream::ReadLengthAndPushLimit() {
|
||||
uint32 length;
|
||||
uint32_t length;
|
||||
return PushLimit(ReadVarint32(&length) ? length : 0);
|
||||
}
|
||||
|
||||
@@ -173,10 +176,7 @@ int CodedInputStream::BytesUntilLimit() const {
|
||||
return current_limit_ - current_position;
|
||||
}
|
||||
|
||||
void CodedInputStream::SetTotalBytesLimit(
|
||||
int total_bytes_limit, int warning_threshold) {
|
||||
(void) warning_threshold;
|
||||
|
||||
void CodedInputStream::SetTotalBytesLimit(int total_bytes_limit) {
|
||||
// Make sure the limit isn't already past, since this could confuse other
|
||||
// code.
|
||||
int current_position = CurrentPosition();
|
||||
@@ -190,11 +190,13 @@ int CodedInputStream::BytesUntilTotalBytesLimit() const {
|
||||
}
|
||||
|
||||
void CodedInputStream::PrintTotalBytesLimitError() {
|
||||
GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too "
|
||||
"big (more than " << total_bytes_limit_
|
||||
<< " bytes). To increase the limit (or to disable these "
|
||||
"warnings), see CodedInputStream::SetTotalBytesLimit() "
|
||||
"in google/protobuf/io/coded_stream.h.";
|
||||
GOOGLE_LOG(ERROR)
|
||||
<< "A protocol message was rejected because it was too "
|
||||
"big (more than "
|
||||
<< total_bytes_limit_
|
||||
<< " bytes). To increase the limit (or to disable these "
|
||||
"warnings), see CodedInputStream::SetTotalBytesLimit() "
|
||||
"in third_party/protobuf/src/google/protobuf/io/coded_stream.h.";
|
||||
}
|
||||
|
||||
bool CodedInputStream::SkipFallback(int count, int original_buffer_size) {
|
||||
@@ -220,8 +222,12 @@ bool CodedInputStream::SkipFallback(int count, int original_buffer_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!input_->Skip(count)) {
|
||||
total_bytes_read_ = input_->ByteCount();
|
||||
return false;
|
||||
}
|
||||
total_bytes_read_ += count;
|
||||
return input_->Skip(count);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) {
|
||||
@@ -233,15 +239,42 @@ bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) {
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadRaw(void* buffer, int size) {
|
||||
return InternalReadRawInline(buffer, size);
|
||||
int current_buffer_size;
|
||||
while ((current_buffer_size = BufferSize()) < size) {
|
||||
// Reading past end of buffer. Copy what we have, then refresh.
|
||||
memcpy(buffer, buffer_, current_buffer_size);
|
||||
buffer = reinterpret_cast<uint8_t*>(buffer) + current_buffer_size;
|
||||
size -= current_buffer_size;
|
||||
Advance(current_buffer_size);
|
||||
if (!Refresh()) return false;
|
||||
}
|
||||
|
||||
memcpy(buffer, buffer_, size);
|
||||
Advance(size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadString(string* buffer, int size) {
|
||||
bool CodedInputStream::ReadString(std::string* buffer, int size) {
|
||||
if (size < 0) return false; // security: size is often user-supplied
|
||||
return InternalReadStringInline(buffer, size);
|
||||
|
||||
if (BufferSize() >= size) {
|
||||
STLStringResizeUninitialized(buffer, size);
|
||||
std::pair<char*, bool> z = as_string_data(buffer);
|
||||
if (z.second) {
|
||||
// Oddly enough, memcpy() requires its first two args to be non-NULL even
|
||||
// if we copy 0 bytes. So, we have ensured that z.first is non-NULL here.
|
||||
GOOGLE_DCHECK(z.first != NULL);
|
||||
memcpy(z.first, buffer_, size);
|
||||
Advance(size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return ReadStringFallback(buffer, size);
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadStringFallback(string* buffer, int size) {
|
||||
bool CodedInputStream::ReadStringFallback(std::string* buffer, int size) {
|
||||
if (!buffer->empty()) {
|
||||
buffer->clear();
|
||||
}
|
||||
@@ -275,11 +308,11 @@ bool CodedInputStream::ReadStringFallback(string* buffer, int size) {
|
||||
}
|
||||
|
||||
|
||||
bool CodedInputStream::ReadLittleEndian32Fallback(uint32* value) {
|
||||
uint8 bytes[sizeof(*value)];
|
||||
bool CodedInputStream::ReadLittleEndian32Fallback(uint32_t* value) {
|
||||
uint8_t bytes[sizeof(*value)];
|
||||
|
||||
const uint8* ptr;
|
||||
if (BufferSize() >= sizeof(*value)) {
|
||||
const uint8_t* ptr;
|
||||
if (BufferSize() >= static_cast<int64_t>(sizeof(*value))) {
|
||||
// Fast path: Enough bytes in the buffer to read directly.
|
||||
ptr = buffer_;
|
||||
Advance(sizeof(*value));
|
||||
@@ -292,11 +325,11 @@ bool CodedInputStream::ReadLittleEndian32Fallback(uint32* value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) {
|
||||
uint8 bytes[sizeof(*value)];
|
||||
bool CodedInputStream::ReadLittleEndian64Fallback(uint64_t* value) {
|
||||
uint8_t bytes[sizeof(*value)];
|
||||
|
||||
const uint8* ptr;
|
||||
if (BufferSize() >= sizeof(*value)) {
|
||||
const uint8_t* ptr;
|
||||
if (BufferSize() >= static_cast<int64_t>(sizeof(*value))) {
|
||||
// Fast path: Enough bytes in the buffer to read directly.
|
||||
ptr = buffer_;
|
||||
Advance(sizeof(*value));
|
||||
@@ -311,111 +344,126 @@ bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) {
|
||||
|
||||
namespace {
|
||||
|
||||
// Decodes varint64 with known size, N, and returns next pointer. Knowing N at
|
||||
// compile time, compiler can generate optimal code. For example, instead of
|
||||
// subtracting 0x80 at each iteration, it subtracts properly shifted mask once.
|
||||
template <size_t N>
|
||||
const uint8_t* DecodeVarint64KnownSize(const uint8_t* buffer, uint64_t* value) {
|
||||
GOOGLE_DCHECK_GT(N, 0);
|
||||
uint64_t result = static_cast<uint64_t>(buffer[N - 1]) << (7 * (N - 1));
|
||||
for (size_t i = 0, offset = 0; i < N - 1; i++, offset += 7) {
|
||||
result += static_cast<uint64_t>(buffer[i] - 0x80) << offset;
|
||||
}
|
||||
*value = result;
|
||||
return buffer + N;
|
||||
}
|
||||
|
||||
// Read a varint from the given buffer, write it to *value, and return a pair.
|
||||
// The first part of the pair is true iff the read was successful. The second
|
||||
// part is buffer + (number of bytes read). This function is always inlined,
|
||||
// so returning a pair is costless.
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
::std::pair<bool, const uint8*> ReadVarint32FromArray(
|
||||
uint32 first_byte, const uint8* buffer,
|
||||
uint32* value);
|
||||
inline ::std::pair<bool, const uint8*> ReadVarint32FromArray(
|
||||
uint32 first_byte, const uint8* buffer, uint32* value) {
|
||||
PROTOBUF_ALWAYS_INLINE
|
||||
::std::pair<bool, const uint8_t*> ReadVarint32FromArray(uint32_t first_byte,
|
||||
const uint8_t* buffer,
|
||||
uint32_t* value);
|
||||
inline ::std::pair<bool, const uint8_t*> ReadVarint32FromArray(
|
||||
uint32_t first_byte, const uint8_t* buffer, uint32_t* value) {
|
||||
// Fast path: We have enough bytes left in the buffer to guarantee that
|
||||
// this read won't cross the end, so we can skip the checks.
|
||||
GOOGLE_DCHECK_EQ(*buffer, first_byte);
|
||||
GOOGLE_DCHECK_EQ(first_byte & 0x80, 0x80) << first_byte;
|
||||
const uint8* ptr = buffer;
|
||||
uint32 b;
|
||||
uint32 result = first_byte - 0x80;
|
||||
const uint8_t* ptr = buffer;
|
||||
uint32_t b;
|
||||
uint32_t result = first_byte - 0x80;
|
||||
++ptr; // We just processed the first byte. Move on to the second.
|
||||
b = *(ptr++); result += b << 7; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++);
|
||||
result += b << 7;
|
||||
if (!(b & 0x80)) goto done;
|
||||
result -= 0x80 << 7;
|
||||
b = *(ptr++); result += b << 14; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++);
|
||||
result += b << 14;
|
||||
if (!(b & 0x80)) goto done;
|
||||
result -= 0x80 << 14;
|
||||
b = *(ptr++); result += b << 21; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++);
|
||||
result += b << 21;
|
||||
if (!(b & 0x80)) goto done;
|
||||
result -= 0x80 << 21;
|
||||
b = *(ptr++); result += b << 28; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++);
|
||||
result += b << 28;
|
||||
if (!(b & 0x80)) goto done;
|
||||
// "result -= 0x80 << 28" is irrevelant.
|
||||
|
||||
// If the input is larger than 32 bits, we still need to read it all
|
||||
// and discard the high-order bits.
|
||||
for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) {
|
||||
b = *(ptr++); if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++);
|
||||
if (!(b & 0x80)) goto done;
|
||||
}
|
||||
|
||||
// We have overrun the maximum size of a varint (10 bytes). Assume
|
||||
// the data is corrupt.
|
||||
return std::make_pair(false, ptr);
|
||||
|
||||
done:
|
||||
done:
|
||||
*value = result;
|
||||
return std::make_pair(true, ptr);
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE::std::pair<bool, const uint8*>
|
||||
ReadVarint64FromArray(const uint8* buffer, uint64* value);
|
||||
inline ::std::pair<bool, const uint8*> ReadVarint64FromArray(
|
||||
const uint8* buffer, uint64* value) {
|
||||
const uint8* ptr = buffer;
|
||||
uint32 b;
|
||||
PROTOBUF_ALWAYS_INLINE::std::pair<bool, const uint8_t*> ReadVarint64FromArray(
|
||||
const uint8_t* buffer, uint64_t* value);
|
||||
inline ::std::pair<bool, const uint8_t*> ReadVarint64FromArray(
|
||||
const uint8_t* buffer, uint64_t* value) {
|
||||
// Assumes varint64 is at least 2 bytes.
|
||||
GOOGLE_DCHECK_GE(buffer[0], 128);
|
||||
|
||||
// Splitting into 32-bit pieces gives better performance on 32-bit
|
||||
// processors.
|
||||
uint32 part0 = 0, part1 = 0, part2 = 0;
|
||||
const uint8_t* next;
|
||||
if (buffer[1] < 128) {
|
||||
next = DecodeVarint64KnownSize<2>(buffer, value);
|
||||
} else if (buffer[2] < 128) {
|
||||
next = DecodeVarint64KnownSize<3>(buffer, value);
|
||||
} else if (buffer[3] < 128) {
|
||||
next = DecodeVarint64KnownSize<4>(buffer, value);
|
||||
} else if (buffer[4] < 128) {
|
||||
next = DecodeVarint64KnownSize<5>(buffer, value);
|
||||
} else if (buffer[5] < 128) {
|
||||
next = DecodeVarint64KnownSize<6>(buffer, value);
|
||||
} else if (buffer[6] < 128) {
|
||||
next = DecodeVarint64KnownSize<7>(buffer, value);
|
||||
} else if (buffer[7] < 128) {
|
||||
next = DecodeVarint64KnownSize<8>(buffer, value);
|
||||
} else if (buffer[8] < 128) {
|
||||
next = DecodeVarint64KnownSize<9>(buffer, value);
|
||||
} else if (buffer[9] < 128) {
|
||||
next = DecodeVarint64KnownSize<10>(buffer, value);
|
||||
} else {
|
||||
// We have overrun the maximum size of a varint (10 bytes). Assume
|
||||
// the data is corrupt.
|
||||
return std::make_pair(false, buffer + 11);
|
||||
}
|
||||
|
||||
b = *(ptr++); part0 = b ; if (!(b & 0x80)) goto done;
|
||||
part0 -= 0x80;
|
||||
b = *(ptr++); part0 += b << 7; if (!(b & 0x80)) goto done;
|
||||
part0 -= 0x80 << 7;
|
||||
b = *(ptr++); part0 += b << 14; if (!(b & 0x80)) goto done;
|
||||
part0 -= 0x80 << 14;
|
||||
b = *(ptr++); part0 += b << 21; if (!(b & 0x80)) goto done;
|
||||
part0 -= 0x80 << 21;
|
||||
b = *(ptr++); part1 = b ; if (!(b & 0x80)) goto done;
|
||||
part1 -= 0x80;
|
||||
b = *(ptr++); part1 += b << 7; if (!(b & 0x80)) goto done;
|
||||
part1 -= 0x80 << 7;
|
||||
b = *(ptr++); part1 += b << 14; if (!(b & 0x80)) goto done;
|
||||
part1 -= 0x80 << 14;
|
||||
b = *(ptr++); part1 += b << 21; if (!(b & 0x80)) goto done;
|
||||
part1 -= 0x80 << 21;
|
||||
b = *(ptr++); part2 = b ; if (!(b & 0x80)) goto done;
|
||||
part2 -= 0x80;
|
||||
b = *(ptr++); part2 += b << 7; if (!(b & 0x80)) goto done;
|
||||
// "part2 -= 0x80 << 7" is irrelevant because (0x80 << 7) << 56 is 0.
|
||||
|
||||
// We have overrun the maximum size of a varint (10 bytes). Assume
|
||||
// the data is corrupt.
|
||||
return std::make_pair(false, ptr);
|
||||
|
||||
done:
|
||||
*value = (static_cast<uint64>(part0)) |
|
||||
(static_cast<uint64>(part1) << 28) |
|
||||
(static_cast<uint64>(part2) << 56);
|
||||
return std::make_pair(true, ptr);
|
||||
return std::make_pair(true, next);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool CodedInputStream::ReadVarint32Slow(uint32* value) {
|
||||
bool CodedInputStream::ReadVarint32Slow(uint32_t* value) {
|
||||
// Directly invoke ReadVarint64Fallback, since we already tried to optimize
|
||||
// for one-byte varints.
|
||||
std::pair<uint64, bool> p = ReadVarint64Fallback();
|
||||
*value = static_cast<uint32>(p.first);
|
||||
std::pair<uint64_t, bool> p = ReadVarint64Fallback();
|
||||
*value = static_cast<uint32_t>(p.first);
|
||||
return p.second;
|
||||
}
|
||||
|
||||
int64 CodedInputStream::ReadVarint32Fallback(uint32 first_byte_or_zero) {
|
||||
int64_t CodedInputStream::ReadVarint32Fallback(uint32_t first_byte_or_zero) {
|
||||
if (BufferSize() >= kMaxVarintBytes ||
|
||||
// Optimization: We're also safe if the buffer is non-empty and it ends
|
||||
// with a byte that would terminate a varint.
|
||||
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
|
||||
GOOGLE_DCHECK_NE(first_byte_or_zero, 0)
|
||||
<< "Caller should provide us with *buffer_ when buffer is non-empty";
|
||||
uint32 temp;
|
||||
::std::pair<bool, const uint8*> p =
|
||||
ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp);
|
||||
uint32_t temp;
|
||||
::std::pair<bool, const uint8_t*> p =
|
||||
ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp);
|
||||
if (!p.first) return -1;
|
||||
buffer_ = p.second;
|
||||
return temp;
|
||||
@@ -423,16 +471,16 @@ int64 CodedInputStream::ReadVarint32Fallback(uint32 first_byte_or_zero) {
|
||||
// Really slow case: we will incur the cost of an extra function call here,
|
||||
// but moving this out of line reduces the size of this function, which
|
||||
// improves the common case. In micro benchmarks, this is worth about 10-15%
|
||||
uint32 temp;
|
||||
return ReadVarint32Slow(&temp) ? static_cast<int64>(temp) : -1;
|
||||
uint32_t temp;
|
||||
return ReadVarint32Slow(&temp) ? static_cast<int64_t>(temp) : -1;
|
||||
}
|
||||
}
|
||||
|
||||
int CodedInputStream::ReadVarintSizeAsIntSlow() {
|
||||
// Directly invoke ReadVarint64Fallback, since we already tried to optimize
|
||||
// for one-byte varints.
|
||||
std::pair<uint64, bool> p = ReadVarint64Fallback();
|
||||
if (!p.second || p.first > static_cast<uint64>(INT_MAX)) return -1;
|
||||
std::pair<uint64_t, bool> p = ReadVarint64Fallback();
|
||||
if (!p.second || p.first > static_cast<uint64_t>(INT_MAX)) return -1;
|
||||
return p.first;
|
||||
}
|
||||
|
||||
@@ -441,9 +489,9 @@ int CodedInputStream::ReadVarintSizeAsIntFallback() {
|
||||
// Optimization: We're also safe if the buffer is non-empty and it ends
|
||||
// with a byte that would terminate a varint.
|
||||
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
|
||||
uint64 temp;
|
||||
::std::pair<bool, const uint8*> p = ReadVarint64FromArray(buffer_, &temp);
|
||||
if (!p.first || temp > static_cast<uint64>(INT_MAX)) return -1;
|
||||
uint64_t temp;
|
||||
::std::pair<bool, const uint8_t*> p = ReadVarint64FromArray(buffer_, &temp);
|
||||
if (!p.first || temp > static_cast<uint64_t>(INT_MAX)) return -1;
|
||||
buffer_ = p.second;
|
||||
return temp;
|
||||
} else {
|
||||
@@ -454,7 +502,7 @@ int CodedInputStream::ReadVarintSizeAsIntFallback() {
|
||||
}
|
||||
}
|
||||
|
||||
uint32 CodedInputStream::ReadTagSlow() {
|
||||
uint32_t CodedInputStream::ReadTagSlow() {
|
||||
if (buffer_ == buffer_end_) {
|
||||
// Call refresh.
|
||||
if (!Refresh()) {
|
||||
@@ -475,12 +523,12 @@ uint32 CodedInputStream::ReadTagSlow() {
|
||||
|
||||
// For the slow path, just do a 64-bit read. Try to optimize for one-byte tags
|
||||
// again, since we have now refreshed the buffer.
|
||||
uint64 result = 0;
|
||||
uint64_t result = 0;
|
||||
if (!ReadVarint64(&result)) return 0;
|
||||
return static_cast<uint32>(result);
|
||||
return static_cast<uint32_t>(result);
|
||||
}
|
||||
|
||||
uint32 CodedInputStream::ReadTagFallback(uint32 first_byte_or_zero) {
|
||||
uint32_t CodedInputStream::ReadTagFallback(uint32_t first_byte_or_zero) {
|
||||
const int buf_size = BufferSize();
|
||||
if (buf_size >= kMaxVarintBytes ||
|
||||
// Optimization: We're also safe if the buffer is non-empty and it ends
|
||||
@@ -491,8 +539,8 @@ uint32 CodedInputStream::ReadTagFallback(uint32 first_byte_or_zero) {
|
||||
++buffer_;
|
||||
return 0;
|
||||
}
|
||||
uint32 tag;
|
||||
::std::pair<bool, const uint8*> p =
|
||||
uint32_t tag;
|
||||
::std::pair<bool, const uint8_t*> p =
|
||||
ReadVarint32FromArray(first_byte_or_zero, buffer_, &tag);
|
||||
if (!p.first) {
|
||||
return 0;
|
||||
@@ -517,13 +565,13 @@ uint32 CodedInputStream::ReadTagFallback(uint32 first_byte_or_zero) {
|
||||
}
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadVarint64Slow(uint64* value) {
|
||||
bool CodedInputStream::ReadVarint64Slow(uint64_t* value) {
|
||||
// Slow path: This read might cross the end of the buffer, so we
|
||||
// need to check and refresh the buffer if and when it does.
|
||||
|
||||
uint64 result = 0;
|
||||
uint64_t result = 0;
|
||||
int count = 0;
|
||||
uint32 b;
|
||||
uint32_t b;
|
||||
|
||||
do {
|
||||
if (count == kMaxVarintBytes) {
|
||||
@@ -537,7 +585,7 @@ bool CodedInputStream::ReadVarint64Slow(uint64* value) {
|
||||
}
|
||||
}
|
||||
b = *buffer_;
|
||||
result |= static_cast<uint64>(b & 0x7F) << (7 * count);
|
||||
result |= static_cast<uint64_t>(b & 0x7F) << (7 * count);
|
||||
Advance(1);
|
||||
++count;
|
||||
} while (b & 0x80);
|
||||
@@ -546,20 +594,20 @@ bool CodedInputStream::ReadVarint64Slow(uint64* value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<uint64, bool> CodedInputStream::ReadVarint64Fallback() {
|
||||
std::pair<uint64_t, bool> CodedInputStream::ReadVarint64Fallback() {
|
||||
if (BufferSize() >= kMaxVarintBytes ||
|
||||
// Optimization: We're also safe if the buffer is non-empty and it ends
|
||||
// with a byte that would terminate a varint.
|
||||
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
|
||||
uint64 temp;
|
||||
::std::pair<bool, const uint8*> p = ReadVarint64FromArray(buffer_, &temp);
|
||||
uint64_t temp;
|
||||
::std::pair<bool, const uint8_t*> p = ReadVarint64FromArray(buffer_, &temp);
|
||||
if (!p.first) {
|
||||
return std::make_pair(0, false);
|
||||
}
|
||||
buffer_ = p.second;
|
||||
return std::make_pair(temp, true);
|
||||
} else {
|
||||
uint64 temp;
|
||||
uint64_t temp;
|
||||
bool success = ReadVarint64Slow(&temp);
|
||||
return std::make_pair(temp, success);
|
||||
}
|
||||
@@ -585,7 +633,7 @@ bool CodedInputStream::Refresh() {
|
||||
const void* void_buffer;
|
||||
int buffer_size;
|
||||
if (NextNonEmpty(input_, &void_buffer, &buffer_size)) {
|
||||
buffer_ = reinterpret_cast<const uint8*>(void_buffer);
|
||||
buffer_ = reinterpret_cast<const uint8_t*>(void_buffer);
|
||||
buffer_end_ = buffer_ + buffer_size;
|
||||
GOOGLE_CHECK_GE(buffer_size, 0);
|
||||
|
||||
@@ -618,174 +666,313 @@ bool CodedInputStream::Refresh() {
|
||||
|
||||
// CodedOutputStream =================================================
|
||||
|
||||
google::protobuf::internal::AtomicWord CodedOutputStream::default_serialization_deterministic_ = 0;
|
||||
|
||||
CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output)
|
||||
: output_(output),
|
||||
buffer_(NULL),
|
||||
buffer_size_(0),
|
||||
total_bytes_(0),
|
||||
had_error_(false),
|
||||
aliasing_enabled_(false),
|
||||
serialization_deterministic_is_overridden_(false) {
|
||||
// Eagerly Refresh() so buffer space is immediately available.
|
||||
Refresh();
|
||||
// The Refresh() may have failed. If the client doesn't write any data,
|
||||
// though, don't consider this an error. If the client does write data, then
|
||||
// another Refresh() will be attempted and it will set the error once again.
|
||||
had_error_ = false;
|
||||
void EpsCopyOutputStream::EnableAliasing(bool enabled) {
|
||||
aliasing_enabled_ = enabled && stream_->AllowsAliasing();
|
||||
}
|
||||
|
||||
CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output,
|
||||
bool do_eager_refresh)
|
||||
: output_(output),
|
||||
buffer_(NULL),
|
||||
buffer_size_(0),
|
||||
total_bytes_(0),
|
||||
had_error_(false),
|
||||
aliasing_enabled_(false),
|
||||
serialization_deterministic_is_overridden_(false) {
|
||||
if (do_eager_refresh) {
|
||||
// Eagerly Refresh() so buffer space is immediately available.
|
||||
Refresh();
|
||||
// The Refresh() may have failed. If the client doesn't write any data,
|
||||
// though, don't consider this an error. If the client does write data, then
|
||||
// another Refresh() will be attempted and it will set the error once again.
|
||||
had_error_ = false;
|
||||
int64_t EpsCopyOutputStream::ByteCount(uint8_t* ptr) const {
|
||||
// Calculate the current offset relative to the end of the stream buffer.
|
||||
int delta = (end_ - ptr) + (buffer_end_ ? 0 : kSlopBytes);
|
||||
return stream_->ByteCount() - delta;
|
||||
}
|
||||
|
||||
// Flushes what's written out to the underlying ZeroCopyOutputStream buffers.
|
||||
// Returns the size remaining in the buffer and sets buffer_end_ to the start
|
||||
// of the remaining buffer, ie. [buffer_end_, buffer_end_ + return value)
|
||||
int EpsCopyOutputStream::Flush(uint8_t* ptr) {
|
||||
while (buffer_end_ && ptr > end_) {
|
||||
int overrun = ptr - end_;
|
||||
GOOGLE_DCHECK(!had_error_);
|
||||
GOOGLE_DCHECK(overrun <= kSlopBytes); // NOLINT
|
||||
ptr = Next() + overrun;
|
||||
if (had_error_) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
CodedOutputStream::~CodedOutputStream() {
|
||||
Trim();
|
||||
}
|
||||
|
||||
void CodedOutputStream::Trim() {
|
||||
if (buffer_size_ > 0) {
|
||||
output_->BackUp(buffer_size_);
|
||||
total_bytes_ -= buffer_size_;
|
||||
buffer_size_ = 0;
|
||||
buffer_ = NULL;
|
||||
int s;
|
||||
if (buffer_end_) {
|
||||
std::memcpy(buffer_end_, buffer_, ptr - buffer_);
|
||||
buffer_end_ += ptr - buffer_;
|
||||
s = end_ - ptr;
|
||||
} else {
|
||||
// The stream is writing directly in the ZeroCopyOutputStream buffer.
|
||||
s = end_ + kSlopBytes - ptr;
|
||||
buffer_end_ = ptr;
|
||||
}
|
||||
GOOGLE_DCHECK(s >= 0); // NOLINT
|
||||
return s;
|
||||
}
|
||||
|
||||
bool CodedOutputStream::Skip(int count) {
|
||||
uint8_t* EpsCopyOutputStream::Trim(uint8_t* ptr) {
|
||||
if (had_error_) return ptr;
|
||||
int s = Flush(ptr);
|
||||
if (s) stream_->BackUp(s);
|
||||
// Reset to initial state (expecting new buffer)
|
||||
buffer_end_ = end_ = buffer_;
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
|
||||
uint8_t* EpsCopyOutputStream::FlushAndResetBuffer(uint8_t* ptr) {
|
||||
if (had_error_) return buffer_;
|
||||
int s = Flush(ptr);
|
||||
if (had_error_) return buffer_;
|
||||
return SetInitialBuffer(buffer_end_, s);
|
||||
}
|
||||
|
||||
bool EpsCopyOutputStream::Skip(int count, uint8_t** pp) {
|
||||
if (count < 0) return false;
|
||||
|
||||
while (count > buffer_size_) {
|
||||
count -= buffer_size_;
|
||||
if (!Refresh()) return false;
|
||||
}
|
||||
|
||||
Advance(count);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodedOutputStream::GetDirectBufferPointer(void** data, int* size) {
|
||||
if (buffer_size_ == 0 && !Refresh()) return false;
|
||||
|
||||
*data = buffer_;
|
||||
*size = buffer_size_;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteRaw(const void* data, int size) {
|
||||
while (buffer_size_ < size) {
|
||||
memcpy(buffer_, data, buffer_size_);
|
||||
size -= buffer_size_;
|
||||
data = reinterpret_cast<const uint8*>(data) + buffer_size_;
|
||||
if (!Refresh()) return;
|
||||
}
|
||||
|
||||
memcpy(buffer_, data, size);
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
uint8* CodedOutputStream::WriteRawToArray(
|
||||
const void* data, int size, uint8* target) {
|
||||
memcpy(target, data, size);
|
||||
return target + size;
|
||||
}
|
||||
|
||||
|
||||
void CodedOutputStream::WriteAliasedRaw(const void* data, int size) {
|
||||
if (size < buffer_size_
|
||||
) {
|
||||
WriteRaw(data, size);
|
||||
} else {
|
||||
Trim();
|
||||
|
||||
total_bytes_ += size;
|
||||
had_error_ |= !output_->WriteAliasedRaw(data, size);
|
||||
}
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteLittleEndian32(uint32 value) {
|
||||
uint8 bytes[sizeof(value)];
|
||||
|
||||
bool use_fast = buffer_size_ >= sizeof(value);
|
||||
uint8* ptr = use_fast ? buffer_ : bytes;
|
||||
|
||||
WriteLittleEndian32ToArray(value, ptr);
|
||||
|
||||
if (use_fast) {
|
||||
Advance(sizeof(value));
|
||||
} else {
|
||||
WriteRaw(bytes, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteLittleEndian64(uint64 value) {
|
||||
uint8 bytes[sizeof(value)];
|
||||
|
||||
bool use_fast = buffer_size_ >= sizeof(value);
|
||||
uint8* ptr = use_fast ? buffer_ : bytes;
|
||||
|
||||
WriteLittleEndian64ToArray(value, ptr);
|
||||
|
||||
if (use_fast) {
|
||||
Advance(sizeof(value));
|
||||
} else {
|
||||
WriteRaw(bytes, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteVarint32SlowPath(uint32 value) {
|
||||
uint8 bytes[kMaxVarint32Bytes];
|
||||
uint8* target = &bytes[0];
|
||||
uint8* end = WriteVarint32ToArray(value, target);
|
||||
int size = end - target;
|
||||
WriteRaw(bytes, size);
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteVarint64SlowPath(uint64 value) {
|
||||
uint8 bytes[kMaxVarintBytes];
|
||||
uint8* target = &bytes[0];
|
||||
uint8* end = WriteVarint64ToArray(value, target);
|
||||
int size = end - target;
|
||||
WriteRaw(bytes, size);
|
||||
}
|
||||
|
||||
bool CodedOutputStream::Refresh() {
|
||||
void* void_buffer;
|
||||
if (output_->Next(&void_buffer, &buffer_size_)) {
|
||||
buffer_ = reinterpret_cast<uint8*>(void_buffer);
|
||||
total_bytes_ += buffer_size_;
|
||||
return true;
|
||||
} else {
|
||||
buffer_ = NULL;
|
||||
buffer_size_ = 0;
|
||||
had_error_ = true;
|
||||
if (had_error_) {
|
||||
*pp = buffer_;
|
||||
return false;
|
||||
}
|
||||
int size = Flush(*pp);
|
||||
if (had_error_) {
|
||||
*pp = buffer_;
|
||||
return false;
|
||||
}
|
||||
void* data = buffer_end_;
|
||||
while (count > size) {
|
||||
count -= size;
|
||||
if (!stream_->Next(&data, &size)) {
|
||||
*pp = Error();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*pp = SetInitialBuffer(static_cast<uint8_t*>(data) + count, size - count);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8* CodedOutputStream::WriteStringWithSizeToArray(const string& str,
|
||||
uint8* target) {
|
||||
GOOGLE_DCHECK_LE(str.size(), kuint32max);
|
||||
bool EpsCopyOutputStream::GetDirectBufferPointer(void** data, int* size,
|
||||
uint8_t** pp) {
|
||||
if (had_error_) {
|
||||
*pp = buffer_;
|
||||
return false;
|
||||
}
|
||||
*size = Flush(*pp);
|
||||
if (had_error_) {
|
||||
*pp = buffer_;
|
||||
return false;
|
||||
}
|
||||
*data = buffer_end_;
|
||||
while (*size == 0) {
|
||||
if (!stream_->Next(data, size)) {
|
||||
*pp = Error();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*pp = SetInitialBuffer(*data, *size);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t* EpsCopyOutputStream::GetDirectBufferForNBytesAndAdvance(int size,
|
||||
uint8_t** pp) {
|
||||
if (had_error_) {
|
||||
*pp = buffer_;
|
||||
return nullptr;
|
||||
}
|
||||
int s = Flush(*pp);
|
||||
if (had_error_) {
|
||||
*pp = buffer_;
|
||||
return nullptr;
|
||||
}
|
||||
if (s >= size) {
|
||||
auto res = buffer_end_;
|
||||
*pp = SetInitialBuffer(buffer_end_ + size, s - size);
|
||||
return res;
|
||||
} else {
|
||||
*pp = SetInitialBuffer(buffer_end_, s);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* EpsCopyOutputStream::Next() {
|
||||
GOOGLE_DCHECK(!had_error_); // NOLINT
|
||||
if (PROTOBUF_PREDICT_FALSE(stream_ == nullptr)) return Error();
|
||||
if (buffer_end_) {
|
||||
// We're in the patch buffer and need to fill up the previous buffer.
|
||||
std::memcpy(buffer_end_, buffer_, end_ - buffer_);
|
||||
uint8_t* ptr;
|
||||
int size;
|
||||
do {
|
||||
void* data;
|
||||
if (PROTOBUF_PREDICT_FALSE(!stream_->Next(&data, &size))) {
|
||||
// Stream has an error, we use the patch buffer to continue to be
|
||||
// able to write.
|
||||
return Error();
|
||||
}
|
||||
ptr = static_cast<uint8_t*>(data);
|
||||
} while (size == 0);
|
||||
if (PROTOBUF_PREDICT_TRUE(size > kSlopBytes)) {
|
||||
std::memcpy(ptr, end_, kSlopBytes);
|
||||
end_ = ptr + size - kSlopBytes;
|
||||
buffer_end_ = nullptr;
|
||||
return ptr;
|
||||
} else {
|
||||
GOOGLE_DCHECK(size > 0); // NOLINT
|
||||
// Buffer to small
|
||||
std::memmove(buffer_, end_, kSlopBytes);
|
||||
buffer_end_ = ptr;
|
||||
end_ = buffer_ + size;
|
||||
return buffer_;
|
||||
}
|
||||
} else {
|
||||
std::memcpy(buffer_, end_, kSlopBytes);
|
||||
buffer_end_ = end_;
|
||||
end_ = buffer_ + kSlopBytes;
|
||||
return buffer_;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* EpsCopyOutputStream::EnsureSpaceFallback(uint8_t* ptr) {
|
||||
do {
|
||||
if (PROTOBUF_PREDICT_FALSE(had_error_)) return buffer_;
|
||||
int overrun = ptr - end_;
|
||||
GOOGLE_DCHECK(overrun >= 0); // NOLINT
|
||||
GOOGLE_DCHECK(overrun <= kSlopBytes); // NOLINT
|
||||
ptr = Next() + overrun;
|
||||
} while (ptr >= end_);
|
||||
GOOGLE_DCHECK(ptr < end_); // NOLINT
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t* EpsCopyOutputStream::WriteRawFallback(const void* data, int size,
|
||||
uint8_t* ptr) {
|
||||
int s = GetSize(ptr);
|
||||
while (s < size) {
|
||||
std::memcpy(ptr, data, s);
|
||||
size -= s;
|
||||
data = static_cast<const uint8_t*>(data) + s;
|
||||
ptr = EnsureSpaceFallback(ptr + s);
|
||||
s = GetSize(ptr);
|
||||
}
|
||||
std::memcpy(ptr, data, size);
|
||||
return ptr + size;
|
||||
}
|
||||
|
||||
uint8_t* EpsCopyOutputStream::WriteAliasedRaw(const void* data, int size,
|
||||
uint8_t* ptr) {
|
||||
if (size < GetSize(ptr)
|
||||
) {
|
||||
return WriteRaw(data, size, ptr);
|
||||
} else {
|
||||
ptr = Trim(ptr);
|
||||
if (stream_->WriteAliasedRaw(data, size)) return ptr;
|
||||
return Error();
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PROTOBUF_LITTLE_ENDIAN
|
||||
uint8_t* EpsCopyOutputStream::WriteRawLittleEndian32(const void* data, int size,
|
||||
uint8_t* ptr) {
|
||||
auto p = static_cast<const uint8_t*>(data);
|
||||
auto end = p + size;
|
||||
while (end - p >= kSlopBytes) {
|
||||
ptr = EnsureSpace(ptr);
|
||||
uint32_t buffer[4];
|
||||
static_assert(sizeof(buffer) == kSlopBytes, "Buffer must be kSlopBytes");
|
||||
std::memcpy(buffer, p, kSlopBytes);
|
||||
p += kSlopBytes;
|
||||
for (auto x : buffer)
|
||||
ptr = CodedOutputStream::WriteLittleEndian32ToArray(x, ptr);
|
||||
}
|
||||
while (p < end) {
|
||||
ptr = EnsureSpace(ptr);
|
||||
uint32_t buffer;
|
||||
std::memcpy(&buffer, p, 4);
|
||||
p += 4;
|
||||
ptr = CodedOutputStream::WriteLittleEndian32ToArray(buffer, ptr);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t* EpsCopyOutputStream::WriteRawLittleEndian64(const void* data, int size,
|
||||
uint8_t* ptr) {
|
||||
auto p = static_cast<const uint8_t*>(data);
|
||||
auto end = p + size;
|
||||
while (end - p >= kSlopBytes) {
|
||||
ptr = EnsureSpace(ptr);
|
||||
uint64_t buffer[2];
|
||||
static_assert(sizeof(buffer) == kSlopBytes, "Buffer must be kSlopBytes");
|
||||
std::memcpy(buffer, p, kSlopBytes);
|
||||
p += kSlopBytes;
|
||||
for (auto x : buffer)
|
||||
ptr = CodedOutputStream::WriteLittleEndian64ToArray(x, ptr);
|
||||
}
|
||||
while (p < end) {
|
||||
ptr = EnsureSpace(ptr);
|
||||
uint64_t buffer;
|
||||
std::memcpy(&buffer, p, 8);
|
||||
p += 8;
|
||||
ptr = CodedOutputStream::WriteLittleEndian64ToArray(buffer, ptr);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
uint8_t* EpsCopyOutputStream::WriteStringMaybeAliasedOutline(uint32_t num,
|
||||
const std::string& s,
|
||||
uint8_t* ptr) {
|
||||
ptr = EnsureSpace(ptr);
|
||||
uint32_t size = s.size();
|
||||
ptr = WriteLengthDelim(num, size, ptr);
|
||||
return WriteRawMaybeAliased(s.data(), size, ptr);
|
||||
}
|
||||
|
||||
uint8_t* EpsCopyOutputStream::WriteStringOutline(uint32_t num, const std::string& s,
|
||||
uint8_t* ptr) {
|
||||
ptr = EnsureSpace(ptr);
|
||||
uint32_t size = s.size();
|
||||
ptr = WriteLengthDelim(num, size, ptr);
|
||||
return WriteRaw(s.data(), size, ptr);
|
||||
}
|
||||
|
||||
std::atomic<bool> CodedOutputStream::default_serialization_deterministic_{
|
||||
false};
|
||||
|
||||
CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* stream,
|
||||
bool do_eager_refresh)
|
||||
: impl_(stream, IsDefaultSerializationDeterministic(), &cur_),
|
||||
start_count_(stream->ByteCount()) {
|
||||
if (do_eager_refresh) {
|
||||
void* data;
|
||||
int size;
|
||||
if (!stream->Next(&data, &size) || size == 0) return;
|
||||
cur_ = impl_.SetInitialBuffer(data, size);
|
||||
}
|
||||
}
|
||||
|
||||
CodedOutputStream::~CodedOutputStream() { Trim(); }
|
||||
|
||||
|
||||
uint8_t* CodedOutputStream::WriteStringWithSizeToArray(const std::string& str,
|
||||
uint8_t* target) {
|
||||
GOOGLE_DCHECK_LE(str.size(), std::numeric_limits<uint32_t>::max());
|
||||
target = WriteVarint32ToArray(str.size(), target);
|
||||
return WriteStringToArray(str, target);
|
||||
}
|
||||
|
||||
uint8_t* CodedOutputStream::WriteVarint32ToArrayOutOfLineHelper(uint32_t value,
|
||||
uint8_t* target) {
|
||||
GOOGLE_DCHECK_GE(value, 0x80);
|
||||
target[0] |= static_cast<uint8_t>(0x80);
|
||||
value >>= 7;
|
||||
target[1] = static_cast<uint8_t>(value);
|
||||
if (value < 0x80) {
|
||||
return target + 2;
|
||||
}
|
||||
target += 2;
|
||||
do {
|
||||
// Turn on continuation bit in the byte we just wrote.
|
||||
target[-1] |= static_cast<uint8_t>(0x80);
|
||||
value >>= 7;
|
||||
*target = static_cast<uint8_t>(value);
|
||||
++target;
|
||||
} while (value >= 0x80);
|
||||
return target;
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
+875
-522
File diff suppressed because it is too large
Load Diff
@@ -1,90 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: jasonh@google.com (Jason Hsueh)
|
||||
//
|
||||
// Implements methods of coded_stream.h that need to be inlined for performance
|
||||
// reasons, but should not be defined in a public header.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
|
||||
#define GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
inline bool CodedInputStream::InternalReadStringInline(string* buffer,
|
||||
int size) {
|
||||
if (size < 0) return false; // security: size is often user-supplied
|
||||
|
||||
if (BufferSize() >= size) {
|
||||
STLStringResizeUninitialized(buffer, size);
|
||||
std::pair<char*, bool> z = as_string_data(buffer);
|
||||
if (z.second) {
|
||||
// Oddly enough, memcpy() requires its first two args to be non-NULL even
|
||||
// if we copy 0 bytes. So, we have ensured that z.first is non-NULL here.
|
||||
GOOGLE_DCHECK(z.first != NULL);
|
||||
memcpy(z.first, buffer_, size);
|
||||
Advance(size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return ReadStringFallback(buffer, size);
|
||||
}
|
||||
|
||||
inline bool CodedInputStream::InternalReadRawInline(void* buffer, int size) {
|
||||
int current_buffer_size;
|
||||
while ((current_buffer_size = BufferSize()) < size) {
|
||||
// Reading past end of buffer. Copy what we have, then refresh.
|
||||
memcpy(buffer, buffer_, current_buffer_size);
|
||||
buffer = reinterpret_cast<uint8*>(buffer) + current_buffer_size;
|
||||
size -= current_buffer_size;
|
||||
Advance(current_buffer_size);
|
||||
if (!Refresh()) return false;
|
||||
}
|
||||
|
||||
memcpy(buffer, buffer_, size);
|
||||
Advance(size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
|
||||
@@ -1,330 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: brianolson@google.com (Brian Olson)
|
||||
//
|
||||
// This file contains the implementation of classes GzipInputStream and
|
||||
// GzipOutputStream.
|
||||
|
||||
|
||||
#if HAVE_ZLIB
|
||||
#include <google/protobuf/io/gzip_stream.h>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
static const int kDefaultBufferSize = 65536;
|
||||
|
||||
GzipInputStream::GzipInputStream(
|
||||
ZeroCopyInputStream* sub_stream, Format format, int buffer_size)
|
||||
: format_(format), sub_stream_(sub_stream), zerror_(Z_OK), byte_count_(0) {
|
||||
zcontext_.state = Z_NULL;
|
||||
zcontext_.zalloc = Z_NULL;
|
||||
zcontext_.zfree = Z_NULL;
|
||||
zcontext_.opaque = Z_NULL;
|
||||
zcontext_.total_out = 0;
|
||||
zcontext_.next_in = NULL;
|
||||
zcontext_.avail_in = 0;
|
||||
zcontext_.total_in = 0;
|
||||
zcontext_.msg = NULL;
|
||||
if (buffer_size == -1) {
|
||||
output_buffer_length_ = kDefaultBufferSize;
|
||||
} else {
|
||||
output_buffer_length_ = buffer_size;
|
||||
}
|
||||
output_buffer_ = operator new(output_buffer_length_);
|
||||
GOOGLE_CHECK(output_buffer_ != NULL);
|
||||
zcontext_.next_out = static_cast<Bytef*>(output_buffer_);
|
||||
zcontext_.avail_out = output_buffer_length_;
|
||||
output_position_ = output_buffer_;
|
||||
}
|
||||
GzipInputStream::~GzipInputStream() {
|
||||
operator delete(output_buffer_);
|
||||
zerror_ = inflateEnd(&zcontext_);
|
||||
}
|
||||
|
||||
static inline int internalInflateInit2(
|
||||
z_stream* zcontext, GzipInputStream::Format format) {
|
||||
int windowBitsFormat = 0;
|
||||
switch (format) {
|
||||
case GzipInputStream::GZIP: windowBitsFormat = 16; break;
|
||||
case GzipInputStream::AUTO: windowBitsFormat = 32; break;
|
||||
case GzipInputStream::ZLIB: windowBitsFormat = 0; break;
|
||||
}
|
||||
return inflateInit2(zcontext, /* windowBits */15 | windowBitsFormat);
|
||||
}
|
||||
|
||||
int GzipInputStream::Inflate(int flush) {
|
||||
if ((zerror_ == Z_OK) && (zcontext_.avail_out == 0)) {
|
||||
// previous inflate filled output buffer. don't change input params yet.
|
||||
} else if (zcontext_.avail_in == 0) {
|
||||
const void* in;
|
||||
int in_size;
|
||||
bool first = zcontext_.next_in == NULL;
|
||||
bool ok = sub_stream_->Next(&in, &in_size);
|
||||
if (!ok) {
|
||||
zcontext_.next_out = NULL;
|
||||
zcontext_.avail_out = 0;
|
||||
return Z_STREAM_END;
|
||||
}
|
||||
zcontext_.next_in = static_cast<Bytef*>(const_cast<void*>(in));
|
||||
zcontext_.avail_in = in_size;
|
||||
if (first) {
|
||||
int error = internalInflateInit2(&zcontext_, format_);
|
||||
if (error != Z_OK) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
}
|
||||
zcontext_.next_out = static_cast<Bytef*>(output_buffer_);
|
||||
zcontext_.avail_out = output_buffer_length_;
|
||||
output_position_ = output_buffer_;
|
||||
int error = inflate(&zcontext_, flush);
|
||||
return error;
|
||||
}
|
||||
|
||||
void GzipInputStream::DoNextOutput(const void** data, int* size) {
|
||||
*data = output_position_;
|
||||
*size = ((uintptr_t)zcontext_.next_out) - ((uintptr_t)output_position_);
|
||||
output_position_ = zcontext_.next_out;
|
||||
}
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool GzipInputStream::Next(const void** data, int* size) {
|
||||
bool ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END)
|
||||
|| (zerror_ == Z_BUF_ERROR);
|
||||
if ((!ok) || (zcontext_.next_out == NULL)) {
|
||||
return false;
|
||||
}
|
||||
if (zcontext_.next_out != output_position_) {
|
||||
DoNextOutput(data, size);
|
||||
return true;
|
||||
}
|
||||
if (zerror_ == Z_STREAM_END) {
|
||||
if (zcontext_.next_out != NULL) {
|
||||
// sub_stream_ may have concatenated streams to follow
|
||||
zerror_ = inflateEnd(&zcontext_);
|
||||
byte_count_ += zcontext_.total_out;
|
||||
if (zerror_ != Z_OK) {
|
||||
return false;
|
||||
}
|
||||
zerror_ = internalInflateInit2(&zcontext_, format_);
|
||||
if (zerror_ != Z_OK) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
*data = NULL;
|
||||
*size = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
zerror_ = Inflate(Z_NO_FLUSH);
|
||||
if ((zerror_ == Z_STREAM_END) && (zcontext_.next_out == NULL)) {
|
||||
// The underlying stream's Next returned false inside Inflate.
|
||||
return false;
|
||||
}
|
||||
ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END)
|
||||
|| (zerror_ == Z_BUF_ERROR);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
DoNextOutput(data, size);
|
||||
return true;
|
||||
}
|
||||
void GzipInputStream::BackUp(int count) {
|
||||
output_position_ = reinterpret_cast<void*>(
|
||||
reinterpret_cast<uintptr_t>(output_position_) - count);
|
||||
}
|
||||
bool GzipInputStream::Skip(int count) {
|
||||
const void* data;
|
||||
int size = 0;
|
||||
bool ok = Next(&data, &size);
|
||||
while (ok && (size < count)) {
|
||||
count -= size;
|
||||
ok = Next(&data, &size);
|
||||
}
|
||||
if (size > count) {
|
||||
BackUp(size - count);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
int64 GzipInputStream::ByteCount() const {
|
||||
int64 ret = byte_count_ + zcontext_.total_out;
|
||||
if (zcontext_.next_out != NULL && output_position_ != NULL) {
|
||||
ret += reinterpret_cast<uintptr_t>(zcontext_.next_out) -
|
||||
reinterpret_cast<uintptr_t>(output_position_);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
|
||||
GzipOutputStream::Options::Options()
|
||||
: format(GZIP),
|
||||
buffer_size(kDefaultBufferSize),
|
||||
compression_level(Z_DEFAULT_COMPRESSION),
|
||||
compression_strategy(Z_DEFAULT_STRATEGY) {}
|
||||
|
||||
GzipOutputStream::GzipOutputStream(ZeroCopyOutputStream* sub_stream) {
|
||||
Init(sub_stream, Options());
|
||||
}
|
||||
|
||||
GzipOutputStream::GzipOutputStream(ZeroCopyOutputStream* sub_stream,
|
||||
const Options& options) {
|
||||
Init(sub_stream, options);
|
||||
}
|
||||
|
||||
void GzipOutputStream::Init(ZeroCopyOutputStream* sub_stream,
|
||||
const Options& options) {
|
||||
sub_stream_ = sub_stream;
|
||||
sub_data_ = NULL;
|
||||
sub_data_size_ = 0;
|
||||
|
||||
input_buffer_length_ = options.buffer_size;
|
||||
input_buffer_ = operator new(input_buffer_length_);
|
||||
GOOGLE_CHECK(input_buffer_ != NULL);
|
||||
|
||||
zcontext_.zalloc = Z_NULL;
|
||||
zcontext_.zfree = Z_NULL;
|
||||
zcontext_.opaque = Z_NULL;
|
||||
zcontext_.next_out = NULL;
|
||||
zcontext_.avail_out = 0;
|
||||
zcontext_.total_out = 0;
|
||||
zcontext_.next_in = NULL;
|
||||
zcontext_.avail_in = 0;
|
||||
zcontext_.total_in = 0;
|
||||
zcontext_.msg = NULL;
|
||||
// default to GZIP format
|
||||
int windowBitsFormat = 16;
|
||||
if (options.format == ZLIB) {
|
||||
windowBitsFormat = 0;
|
||||
}
|
||||
zerror_ = deflateInit2(
|
||||
&zcontext_,
|
||||
options.compression_level,
|
||||
Z_DEFLATED,
|
||||
/* windowBits */15 | windowBitsFormat,
|
||||
/* memLevel (default) */8,
|
||||
options.compression_strategy);
|
||||
}
|
||||
|
||||
GzipOutputStream::~GzipOutputStream() {
|
||||
Close();
|
||||
operator delete(input_buffer_);
|
||||
}
|
||||
|
||||
// private
|
||||
int GzipOutputStream::Deflate(int flush) {
|
||||
int error = Z_OK;
|
||||
do {
|
||||
if ((sub_data_ == NULL) || (zcontext_.avail_out == 0)) {
|
||||
bool ok = sub_stream_->Next(&sub_data_, &sub_data_size_);
|
||||
if (!ok) {
|
||||
sub_data_ = NULL;
|
||||
sub_data_size_ = 0;
|
||||
return Z_BUF_ERROR;
|
||||
}
|
||||
GOOGLE_CHECK_GT(sub_data_size_, 0);
|
||||
zcontext_.next_out = static_cast<Bytef*>(sub_data_);
|
||||
zcontext_.avail_out = sub_data_size_;
|
||||
}
|
||||
error = deflate(&zcontext_, flush);
|
||||
} while (error == Z_OK && zcontext_.avail_out == 0);
|
||||
if ((flush == Z_FULL_FLUSH) || (flush == Z_FINISH)) {
|
||||
// Notify lower layer of data.
|
||||
sub_stream_->BackUp(zcontext_.avail_out);
|
||||
// We don't own the buffer anymore.
|
||||
sub_data_ = NULL;
|
||||
sub_data_size_ = 0;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool GzipOutputStream::Next(void** data, int* size) {
|
||||
if ((zerror_ != Z_OK) && (zerror_ != Z_BUF_ERROR)) {
|
||||
return false;
|
||||
}
|
||||
if (zcontext_.avail_in != 0) {
|
||||
zerror_ = Deflate(Z_NO_FLUSH);
|
||||
if (zerror_ != Z_OK) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (zcontext_.avail_in == 0) {
|
||||
// all input was consumed. reset the buffer.
|
||||
zcontext_.next_in = static_cast<Bytef*>(input_buffer_);
|
||||
zcontext_.avail_in = input_buffer_length_;
|
||||
*data = input_buffer_;
|
||||
*size = input_buffer_length_;
|
||||
} else {
|
||||
// The loop in Deflate should consume all avail_in
|
||||
GOOGLE_LOG(DFATAL) << "Deflate left bytes unconsumed";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void GzipOutputStream::BackUp(int count) {
|
||||
GOOGLE_CHECK_GE(zcontext_.avail_in, count);
|
||||
zcontext_.avail_in -= count;
|
||||
}
|
||||
int64 GzipOutputStream::ByteCount() const {
|
||||
return zcontext_.total_in + zcontext_.avail_in;
|
||||
}
|
||||
|
||||
bool GzipOutputStream::Flush() {
|
||||
zerror_ = Deflate(Z_FULL_FLUSH);
|
||||
// Return true if the flush succeeded or if it was a no-op.
|
||||
return (zerror_ == Z_OK) ||
|
||||
(zerror_ == Z_BUF_ERROR && zcontext_.avail_in == 0 &&
|
||||
zcontext_.avail_out != 0);
|
||||
}
|
||||
|
||||
bool GzipOutputStream::Close() {
|
||||
if ((zerror_ != Z_OK) && (zerror_ != Z_BUF_ERROR)) {
|
||||
return false;
|
||||
}
|
||||
do {
|
||||
zerror_ = Deflate(Z_FINISH);
|
||||
} while (zerror_ == Z_OK);
|
||||
zerror_ = deflateEnd(&zcontext_);
|
||||
bool ok = zerror_ == Z_OK;
|
||||
zerror_ = Z_STREAM_END;
|
||||
return ok;
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // HAVE_ZLIB
|
||||
@@ -1,209 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: brianolson@google.com (Brian Olson)
|
||||
//
|
||||
// This file contains the definition for classes GzipInputStream and
|
||||
// GzipOutputStream.
|
||||
//
|
||||
// GzipInputStream decompresses data from an underlying
|
||||
// ZeroCopyInputStream and provides the decompressed data as a
|
||||
// ZeroCopyInputStream.
|
||||
//
|
||||
// GzipOutputStream is an ZeroCopyOutputStream that compresses data to
|
||||
// an underlying ZeroCopyOutputStream.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
|
||||
#define GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <zlib.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// A ZeroCopyInputStream that reads compressed data through zlib
|
||||
class LIBPROTOBUF_EXPORT GzipInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Format key for constructor
|
||||
enum Format {
|
||||
// zlib will autodetect gzip header or deflate stream
|
||||
AUTO = 0,
|
||||
|
||||
// GZIP streams have some extra header data for file attributes.
|
||||
GZIP = 1,
|
||||
|
||||
// Simpler zlib stream format.
|
||||
ZLIB = 2,
|
||||
};
|
||||
|
||||
// buffer_size and format may be -1 for default of 64kB and GZIP format
|
||||
explicit GzipInputStream(
|
||||
ZeroCopyInputStream* sub_stream,
|
||||
Format format = AUTO,
|
||||
int buffer_size = -1);
|
||||
virtual ~GzipInputStream();
|
||||
|
||||
// Return last error message or NULL if no error.
|
||||
inline const char* ZlibErrorMessage() const {
|
||||
return zcontext_.msg;
|
||||
}
|
||||
inline int ZlibErrorCode() const {
|
||||
return zerror_;
|
||||
}
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
Format format_;
|
||||
|
||||
ZeroCopyInputStream* sub_stream_;
|
||||
|
||||
z_stream zcontext_;
|
||||
int zerror_;
|
||||
|
||||
void* output_buffer_;
|
||||
void* output_position_;
|
||||
size_t output_buffer_length_;
|
||||
int64 byte_count_;
|
||||
|
||||
int Inflate(int flush);
|
||||
void DoNextOutput(const void** data, int* size);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipInputStream);
|
||||
};
|
||||
|
||||
|
||||
class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Format key for constructor
|
||||
enum Format {
|
||||
// GZIP streams have some extra header data for file attributes.
|
||||
GZIP = 1,
|
||||
|
||||
// Simpler zlib stream format.
|
||||
ZLIB = 2,
|
||||
};
|
||||
|
||||
struct Options {
|
||||
// Defaults to GZIP.
|
||||
Format format;
|
||||
|
||||
// What size buffer to use internally. Defaults to 64kB.
|
||||
int buffer_size;
|
||||
|
||||
// A number between 0 and 9, where 0 is no compression and 9 is best
|
||||
// compression. Defaults to Z_DEFAULT_COMPRESSION (see zlib.h).
|
||||
int compression_level;
|
||||
|
||||
// Defaults to Z_DEFAULT_STRATEGY. Can also be set to Z_FILTERED,
|
||||
// Z_HUFFMAN_ONLY, or Z_RLE. See the documentation for deflateInit2 in
|
||||
// zlib.h for definitions of these constants.
|
||||
int compression_strategy;
|
||||
|
||||
Options(); // Initializes with default values.
|
||||
};
|
||||
|
||||
// Create a GzipOutputStream with default options.
|
||||
explicit GzipOutputStream(ZeroCopyOutputStream* sub_stream);
|
||||
|
||||
// Create a GzipOutputStream with the given options.
|
||||
GzipOutputStream(
|
||||
ZeroCopyOutputStream* sub_stream,
|
||||
const Options& options);
|
||||
|
||||
virtual ~GzipOutputStream();
|
||||
|
||||
// Return last error message or NULL if no error.
|
||||
inline const char* ZlibErrorMessage() const {
|
||||
return zcontext_.msg;
|
||||
}
|
||||
inline int ZlibErrorCode() const {
|
||||
return zerror_;
|
||||
}
|
||||
|
||||
// Flushes data written so far to zipped data in the underlying stream.
|
||||
// It is the caller's responsibility to flush the underlying stream if
|
||||
// necessary.
|
||||
// Compression may be less efficient stopping and starting around flushes.
|
||||
// Returns true if no error.
|
||||
//
|
||||
// Please ensure that block size is > 6. Here is an excerpt from the zlib
|
||||
// doc that explains why:
|
||||
//
|
||||
// In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out
|
||||
// is greater than six to avoid repeated flush markers due to
|
||||
// avail_out == 0 on return.
|
||||
bool Flush();
|
||||
|
||||
// Writes out all data and closes the gzip stream.
|
||||
// It is the caller's responsibility to close the underlying stream if
|
||||
// necessary.
|
||||
// Returns true if no error.
|
||||
bool Close();
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
ZeroCopyOutputStream* sub_stream_;
|
||||
// Result from calling Next() on sub_stream_
|
||||
void* sub_data_;
|
||||
int sub_data_size_;
|
||||
|
||||
z_stream zcontext_;
|
||||
int zerror_;
|
||||
void* input_buffer_;
|
||||
size_t input_buffer_length_;
|
||||
|
||||
// Shared constructor code.
|
||||
void Init(ZeroCopyOutputStream* sub_stream, const Options& options);
|
||||
|
||||
// Do some compression.
|
||||
// Takes zlib flush mode.
|
||||
// Returns zlib error code.
|
||||
int Deflate(int flush);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipOutputStream);
|
||||
};
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
|
||||
+82
-25
@@ -29,7 +29,9 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: laszlocsomor@google.com (Laszlo Csomor)
|
||||
//
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
// Implementation for long-path-aware open/mkdir/access/etc. on Windows, as well
|
||||
// as for the supporting utility functions.
|
||||
//
|
||||
@@ -40,13 +42,15 @@
|
||||
//
|
||||
// This file is only used on Windows, it's empty on other platforms.
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32) && !defined(_XBOX_ONE)
|
||||
|
||||
// Comment this out to fall back to using the ANSI versions (open, mkdir, ...)
|
||||
// instead of the Unicode ones (_wopen, _wmkdir, ...). Doing so can be useful to
|
||||
// debug failing tests if that's caused by the long path support.
|
||||
#define SUPPORT_LONGPATHS
|
||||
|
||||
#include <google/protobuf/io/io_win32.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <direct.h>
|
||||
#include <errno.h>
|
||||
@@ -55,10 +59,12 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <wctype.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <google/protobuf/stubs/io_win32.h>
|
||||
#include <google/protobuf/stubs/scoped_ptr.h>
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
@@ -67,7 +73,7 @@
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
namespace io {
|
||||
namespace win32 {
|
||||
namespace {
|
||||
|
||||
@@ -91,7 +97,7 @@ struct CharTraits<wchar_t> {
|
||||
|
||||
template <typename char_type>
|
||||
bool null_or_empty(const char_type* s) {
|
||||
return s == NULL || *s == 0;
|
||||
return s == nullptr || *s == 0;
|
||||
}
|
||||
|
||||
// Returns true if the path starts with a drive letter, e.g. "c:".
|
||||
@@ -151,12 +157,13 @@ wstring normalize(wstring path) {
|
||||
|
||||
static const wstring dot(L".");
|
||||
static const wstring dotdot(L"..");
|
||||
const WCHAR* p = path.c_str();
|
||||
|
||||
std::vector<wstring> segments;
|
||||
int segment_start = -1;
|
||||
// Find the path segments in `path` (separated by "/").
|
||||
for (int i = 0;; ++i) {
|
||||
if (!is_separator(path[i]) && path[i] != L'\0') {
|
||||
if (!is_separator(p[i]) && p[i] != L'\0') {
|
||||
// The current character does not end a segment, so start one unless it's
|
||||
// already started.
|
||||
if (segment_start < 0) {
|
||||
@@ -165,7 +172,7 @@ wstring normalize(wstring path) {
|
||||
} else if (segment_start >= 0 && i > segment_start) {
|
||||
// The current character is "/" or "\0", so this ends a segment.
|
||||
// Add that to `segments` if there's anything to add; handle "." and "..".
|
||||
wstring segment(path, segment_start, i - segment_start);
|
||||
wstring segment(p, segment_start, i - segment_start);
|
||||
segment_start = -1;
|
||||
if (segment == dotdot) {
|
||||
if (!segments.empty() &&
|
||||
@@ -176,7 +183,7 @@ wstring normalize(wstring path) {
|
||||
segments.push_back(segment);
|
||||
}
|
||||
}
|
||||
if (path[i] == L'\0') {
|
||||
if (p[i] == L'\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -199,7 +206,7 @@ wstring normalize(wstring path) {
|
||||
result << segments[i];
|
||||
}
|
||||
// Preserve trailing separator if the input contained it.
|
||||
if (!path.empty() && is_separator(path[path.size() - 1])) {
|
||||
if (!path.empty() && is_separator(p[path.size() - 1])) {
|
||||
result << L'\\';
|
||||
}
|
||||
return result.str();
|
||||
@@ -224,11 +231,11 @@ bool as_windows_path(const char* path, wstring* result) {
|
||||
|
||||
|
||||
if (!is_path_absolute(wpath.c_str())) {
|
||||
int size = ::GetCurrentDirectoryW(0, NULL);
|
||||
int size = ::GetCurrentDirectoryW(0, nullptr);
|
||||
if (size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
return false;
|
||||
}
|
||||
scoped_array<WCHAR> wcwd(new WCHAR[size]);
|
||||
std::unique_ptr<WCHAR[]> wcwd(new WCHAR[size]);
|
||||
::GetCurrentDirectoryW(size, wcwd.get());
|
||||
wpath = join_paths(wcwd.get(), wpath);
|
||||
}
|
||||
@@ -259,7 +266,7 @@ int open(const char* path, int flags, int mode) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int mkdir(const char* path, int _mode) {
|
||||
int mkdir(const char* path, int /*_mode*/) {
|
||||
#ifdef SUPPORT_LONGPATHS
|
||||
wstring wpath;
|
||||
if (!as_windows_path(path, &wpath)) {
|
||||
@@ -315,17 +322,17 @@ FILE* fopen(const char* path, const char* mode) {
|
||||
#ifdef SUPPORT_LONGPATHS
|
||||
if (null_or_empty(path)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
wstring wpath;
|
||||
if (!as_windows_path(path, &wpath)) {
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
wstring wmode;
|
||||
if (!strings::utf8_to_wcs(mode, &wmode)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
return ::_wfopen(wpath.c_str(), wmode.c_str());
|
||||
#else
|
||||
@@ -333,7 +340,7 @@ FILE* fopen(const char* path, const char* mode) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int close(int fd) { return ::close(fd); }
|
||||
int close(int fd) { return ::_close(fd); }
|
||||
|
||||
int dup(int fd) { return ::_dup(fd); }
|
||||
|
||||
@@ -354,6 +361,56 @@ wstring testonly_utf8_to_winpath(const char* path) {
|
||||
return as_windows_path(path, &wpath) ? wpath : wstring();
|
||||
}
|
||||
|
||||
ExpandWildcardsResult ExpandWildcards(
|
||||
const string& path, std::function<void(const string&)> consume) {
|
||||
if (path.find_first_of("*?") == string::npos) {
|
||||
// There are no wildcards in the path, we don't need to expand it.
|
||||
consume(path);
|
||||
return ExpandWildcardsResult::kSuccess;
|
||||
}
|
||||
|
||||
wstring wpath;
|
||||
if (!as_windows_path(path.c_str(), &wpath)) {
|
||||
return ExpandWildcardsResult::kErrorInputPathConversion;
|
||||
}
|
||||
|
||||
static const wstring kDot = L".";
|
||||
static const wstring kDotDot = L"..";
|
||||
WIN32_FIND_DATAW metadata;
|
||||
HANDLE handle = ::FindFirstFileW(wpath.c_str(), &metadata);
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
// The pattern does not match any files (or directories).
|
||||
return ExpandWildcardsResult::kErrorNoMatchingFile;
|
||||
}
|
||||
|
||||
string::size_type pos = path.find_last_of("\\/");
|
||||
string dirname;
|
||||
if (pos != string::npos) {
|
||||
dirname = path.substr(0, pos + 1);
|
||||
}
|
||||
|
||||
ExpandWildcardsResult matched = ExpandWildcardsResult::kErrorNoMatchingFile;
|
||||
do {
|
||||
// Ignore ".", "..", and directories.
|
||||
if ((metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 &&
|
||||
kDot != metadata.cFileName && kDotDot != metadata.cFileName) {
|
||||
matched = ExpandWildcardsResult::kSuccess;
|
||||
string filename;
|
||||
if (!strings::wcs_to_utf8(metadata.cFileName, &filename)) {
|
||||
return ExpandWildcardsResult::kErrorOutputPathConversion;
|
||||
}
|
||||
|
||||
if (dirname.empty()) {
|
||||
consume(filename);
|
||||
} else {
|
||||
consume(dirname + filename);
|
||||
}
|
||||
}
|
||||
} while (::FindNextFileW(handle, &metadata));
|
||||
FindClose(handle);
|
||||
return matched;
|
||||
}
|
||||
|
||||
namespace strings {
|
||||
|
||||
bool wcs_to_mbs(const WCHAR* s, string* out, bool outUtf8) {
|
||||
@@ -364,15 +421,15 @@ bool wcs_to_mbs(const WCHAR* s, string* out, bool outUtf8) {
|
||||
BOOL usedDefaultChar = FALSE;
|
||||
SetLastError(0);
|
||||
int size = WideCharToMultiByte(
|
||||
outUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, NULL, 0, NULL,
|
||||
outUtf8 ? NULL : &usedDefaultChar);
|
||||
outUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, nullptr, 0, nullptr,
|
||||
outUtf8 ? nullptr : &usedDefaultChar);
|
||||
if ((size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
|| usedDefaultChar) {
|
||||
return false;
|
||||
}
|
||||
scoped_array<CHAR> astr(new CHAR[size]);
|
||||
std::unique_ptr<CHAR[]> astr(new CHAR[size]);
|
||||
WideCharToMultiByte(
|
||||
outUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, astr.get(), size, NULL, NULL);
|
||||
outUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, astr.get(), size, nullptr, nullptr);
|
||||
out->assign(astr.get());
|
||||
return true;
|
||||
}
|
||||
@@ -385,11 +442,11 @@ bool mbs_to_wcs(const char* s, wstring* out, bool inUtf8) {
|
||||
|
||||
SetLastError(0);
|
||||
int size =
|
||||
MultiByteToWideChar(inUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, NULL, 0);
|
||||
MultiByteToWideChar(inUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, nullptr, 0);
|
||||
if (size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
return false;
|
||||
}
|
||||
scoped_array<WCHAR> wstr(new WCHAR[size]);
|
||||
std::unique_ptr<WCHAR[]> wstr(new WCHAR[size]);
|
||||
MultiByteToWideChar(
|
||||
inUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, wstr.get(), size + 1);
|
||||
out->assign(wstr.get());
|
||||
@@ -406,7 +463,7 @@ bool wcs_to_utf8(const wchar_t* input, string* out) {
|
||||
|
||||
} // namespace strings
|
||||
} // namespace win32
|
||||
} // namespace internal
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
+51
-27
@@ -29,68 +29,90 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: laszlocsomor@google.com (Laszlo Csomor)
|
||||
//
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
// This file contains the declarations for Windows implementations of
|
||||
// commonly used POSIX functions such as open(2) and access(2), as well
|
||||
// as macro definitions for flags of these functions.
|
||||
//
|
||||
// By including this file you'll redefine open/access/etc. to
|
||||
// ::google::protobuf::internal::win32::{open/access/etc.}.
|
||||
// ::google::protobuf::io::win32::{open/access/etc.}.
|
||||
// Make sure you don't include a header that attempts to redeclare or
|
||||
// redefine these functions, that'll lead to confusing compilation
|
||||
// errors. It's best to #include this file as the last one to ensure that.
|
||||
//
|
||||
// This file is only used on Windows, it's empty on other platforms.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__
|
||||
#ifndef GOOGLE_PROTOBUF_IO_IO_WIN32_H__
|
||||
#define GOOGLE_PROTOBUF_IO_IO_WIN32_H__
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
// Compilers on Windows other than MSVC (e.g. Cygwin, MinGW32) define the
|
||||
// following functions already, except for mkdir.
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
namespace io {
|
||||
namespace win32 {
|
||||
|
||||
LIBPROTOBUF_EXPORT FILE* fopen(const char* path, const char* mode);
|
||||
LIBPROTOBUF_EXPORT int access(const char* path, int mode);
|
||||
LIBPROTOBUF_EXPORT int chdir(const char* path);
|
||||
LIBPROTOBUF_EXPORT int close(int fd);
|
||||
LIBPROTOBUF_EXPORT int dup(int fd);
|
||||
LIBPROTOBUF_EXPORT int dup2(int fd1, int fd2);
|
||||
LIBPROTOBUF_EXPORT int mkdir(const char* path, int _mode);
|
||||
LIBPROTOBUF_EXPORT int open(const char* path, int flags, int mode = 0);
|
||||
LIBPROTOBUF_EXPORT int read(int fd, void* buffer, size_t size);
|
||||
LIBPROTOBUF_EXPORT int setmode(int fd, int mode);
|
||||
LIBPROTOBUF_EXPORT int stat(const char* path, struct _stat* buffer);
|
||||
LIBPROTOBUF_EXPORT int write(int fd, const void* buffer, size_t size);
|
||||
LIBPROTOBUF_EXPORT std::wstring testonly_utf8_to_winpath(const char* path);
|
||||
PROTOBUF_EXPORT FILE* fopen(const char* path, const char* mode);
|
||||
PROTOBUF_EXPORT int access(const char* path, int mode);
|
||||
PROTOBUF_EXPORT int chdir(const char* path);
|
||||
PROTOBUF_EXPORT int close(int fd);
|
||||
PROTOBUF_EXPORT int dup(int fd);
|
||||
PROTOBUF_EXPORT int dup2(int fd1, int fd2);
|
||||
PROTOBUF_EXPORT int mkdir(const char* path, int _mode);
|
||||
PROTOBUF_EXPORT int open(const char* path, int flags, int mode = 0);
|
||||
PROTOBUF_EXPORT int read(int fd, void* buffer, size_t size);
|
||||
PROTOBUF_EXPORT int setmode(int fd, int mode);
|
||||
PROTOBUF_EXPORT int stat(const char* path, struct _stat* buffer);
|
||||
PROTOBUF_EXPORT int write(int fd, const void* buffer, size_t size);
|
||||
PROTOBUF_EXPORT std::wstring testonly_utf8_to_winpath(const char* path);
|
||||
|
||||
enum class ExpandWildcardsResult {
|
||||
kSuccess = 0,
|
||||
kErrorNoMatchingFile = 1,
|
||||
kErrorInputPathConversion = 2,
|
||||
kErrorOutputPathConversion = 3,
|
||||
};
|
||||
|
||||
// Expand wildcards in a path pattern, feed the result to a consumer function.
|
||||
//
|
||||
// `path` must be a valid, Windows-style path. It may be absolute, or relative
|
||||
// to the current working directory, and it may contain wildcards ("*" and "?")
|
||||
// in the last path segment. This function passes all matching file names to
|
||||
// `consume`. The resulting paths may not be absolute nor normalized.
|
||||
//
|
||||
// The function returns a value from `ExpandWildcardsResult`.
|
||||
PROTOBUF_EXPORT ExpandWildcardsResult ExpandWildcards(
|
||||
const std::string& path, std::function<void(const std::string&)> consume);
|
||||
|
||||
namespace strings {
|
||||
|
||||
// Convert from UTF-16 to Active-Code-Page-encoded or to UTF-8-encoded text.
|
||||
LIBPROTOBUF_EXPORT bool wcs_to_mbs(
|
||||
const wchar_t* s, std::string* out, bool outUtf8);
|
||||
PROTOBUF_EXPORT bool wcs_to_mbs(const wchar_t* s, std::string* out,
|
||||
bool outUtf8);
|
||||
|
||||
// Convert from Active-Code-Page-encoded or UTF-8-encoded text to UTF-16.
|
||||
LIBPROTOBUF_EXPORT bool mbs_to_wcs(
|
||||
const char* s, std::wstring* out, bool inUtf8);
|
||||
PROTOBUF_EXPORT bool mbs_to_wcs(const char* s, std::wstring* out, bool inUtf8);
|
||||
|
||||
// Convert from UTF-8-encoded text to UTF-16.
|
||||
LIBPROTOBUF_EXPORT bool utf8_to_wcs(const char* input, std::wstring* out);
|
||||
PROTOBUF_EXPORT bool utf8_to_wcs(const char* input, std::wstring* out);
|
||||
|
||||
// Convert from UTF-16-encoded text to UTF-8.
|
||||
LIBPROTOBUF_EXPORT bool wcs_to_utf8(const wchar_t* input, std::string* out);
|
||||
PROTOBUF_EXPORT bool wcs_to_utf8(const wchar_t* input, std::string* out);
|
||||
|
||||
} // namespace strings
|
||||
|
||||
} // namespace win32
|
||||
} // namespace internal
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
@@ -110,6 +132,8 @@ LIBPROTOBUF_EXPORT bool wcs_to_utf8(const wchar_t* input, std::string* out);
|
||||
#define STDOUT_FILENO 1
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__
|
||||
#endif // GOOGLE_PROTOBUF_IO_IO_WIN32_H__
|
||||
@@ -37,7 +37,6 @@
|
||||
// documentation generator.
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
|
||||
// Auxiliary classes used for I/O.
|
||||
|
||||
-372
@@ -1,372 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter)
|
||||
: variable_delimiter_(variable_delimiter),
|
||||
output_(output),
|
||||
buffer_(NULL),
|
||||
buffer_size_(0),
|
||||
offset_(0),
|
||||
at_start_of_line_(true),
|
||||
failed_(false),
|
||||
annotation_collector_(NULL) {}
|
||||
|
||||
Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter,
|
||||
AnnotationCollector* annotation_collector)
|
||||
: variable_delimiter_(variable_delimiter),
|
||||
output_(output),
|
||||
buffer_(NULL),
|
||||
buffer_size_(0),
|
||||
offset_(0),
|
||||
at_start_of_line_(true),
|
||||
failed_(false),
|
||||
annotation_collector_(annotation_collector) {}
|
||||
|
||||
Printer::~Printer() {
|
||||
// Only BackUp() if we have called Next() at least once and never failed.
|
||||
if (buffer_size_ > 0 && !failed_) {
|
||||
output_->BackUp(buffer_size_);
|
||||
}
|
||||
}
|
||||
|
||||
bool Printer::GetSubstitutionRange(const char* varname,
|
||||
std::pair<size_t, size_t>* range) {
|
||||
std::map<string, std::pair<size_t, size_t> >::const_iterator iter =
|
||||
substitutions_.find(varname);
|
||||
if (iter == substitutions_.end()) {
|
||||
GOOGLE_LOG(DFATAL) << " Undefined variable in annotation: " << varname;
|
||||
return false;
|
||||
}
|
||||
if (iter->second.first > iter->second.second) {
|
||||
GOOGLE_LOG(DFATAL) << " Variable used for annotation used multiple times: "
|
||||
<< varname;
|
||||
return false;
|
||||
}
|
||||
*range = iter->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Printer::Annotate(const char* begin_varname, const char* end_varname,
|
||||
const string& file_path, const std::vector<int>& path) {
|
||||
if (annotation_collector_ == NULL) {
|
||||
// Can't generate signatures with this Printer.
|
||||
return;
|
||||
}
|
||||
std::pair<size_t, size_t> begin, end;
|
||||
if (!GetSubstitutionRange(begin_varname, &begin) ||
|
||||
!GetSubstitutionRange(end_varname, &end)) {
|
||||
return;
|
||||
}
|
||||
if (begin.first > end.second) {
|
||||
GOOGLE_LOG(DFATAL) << " Annotation has negative length from " << begin_varname
|
||||
<< " to " << end_varname;
|
||||
} else {
|
||||
annotation_collector_->AddAnnotation(begin.first, end.second, file_path,
|
||||
path);
|
||||
}
|
||||
}
|
||||
|
||||
void Printer::Print(const std::map<string, string>& variables,
|
||||
const char* text) {
|
||||
int size = strlen(text);
|
||||
int pos = 0; // The number of bytes we've written so far.
|
||||
substitutions_.clear();
|
||||
line_start_variables_.clear();
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (text[i] == '\n') {
|
||||
// Saw newline. If there is more text, we may need to insert an indent
|
||||
// here. So, write what we have so far, including the '\n'.
|
||||
WriteRaw(text + pos, i - pos + 1);
|
||||
pos = i + 1;
|
||||
|
||||
// Setting this true will cause the next WriteRaw() to insert an indent
|
||||
// first.
|
||||
at_start_of_line_ = true;
|
||||
line_start_variables_.clear();
|
||||
|
||||
} else if (text[i] == variable_delimiter_) {
|
||||
// Saw the start of a variable name.
|
||||
|
||||
// Write what we have so far.
|
||||
WriteRaw(text + pos, i - pos);
|
||||
pos = i + 1;
|
||||
|
||||
// Find closing delimiter.
|
||||
const char* end = strchr(text + pos, variable_delimiter_);
|
||||
if (end == NULL) {
|
||||
GOOGLE_LOG(DFATAL) << " Unclosed variable name.";
|
||||
end = text + pos;
|
||||
}
|
||||
int endpos = end - text;
|
||||
|
||||
string varname(text + pos, endpos - pos);
|
||||
if (varname.empty()) {
|
||||
// Two delimiters in a row reduce to a literal delimiter character.
|
||||
WriteRaw(&variable_delimiter_, 1);
|
||||
} else {
|
||||
// Replace with the variable's value.
|
||||
std::map<string, string>::const_iterator iter = variables.find(varname);
|
||||
if (iter == variables.end()) {
|
||||
GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname;
|
||||
} else {
|
||||
if (at_start_of_line_ && iter->second.empty()) {
|
||||
line_start_variables_.push_back(varname);
|
||||
}
|
||||
WriteRaw(iter->second.data(), iter->second.size());
|
||||
std::pair<std::map<string, std::pair<size_t, size_t> >::iterator,
|
||||
bool>
|
||||
inserted = substitutions_.insert(std::make_pair(
|
||||
varname,
|
||||
std::make_pair(offset_ - iter->second.size(), offset_)));
|
||||
if (!inserted.second) {
|
||||
// This variable was used multiple times. Make its span have
|
||||
// negative length so we can detect it if it gets used in an
|
||||
// annotation.
|
||||
inserted.first->second = std::make_pair(1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Advance past this variable.
|
||||
i = endpos;
|
||||
pos = endpos + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Write the rest.
|
||||
WriteRaw(text + pos, size - pos);
|
||||
}
|
||||
|
||||
void Printer::Print(const char* text) {
|
||||
static std::map<string, string> empty;
|
||||
Print(empty, text);
|
||||
}
|
||||
|
||||
void Printer::Print(const char* text,
|
||||
const char* variable, const string& value) {
|
||||
std::map<string, string> vars;
|
||||
vars[variable] = value;
|
||||
Print(vars, text);
|
||||
}
|
||||
|
||||
void Printer::Print(const char* text,
|
||||
const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2) {
|
||||
std::map<string, string> vars;
|
||||
vars[variable1] = value1;
|
||||
vars[variable2] = value2;
|
||||
Print(vars, text);
|
||||
}
|
||||
|
||||
void Printer::Print(const char* text,
|
||||
const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3) {
|
||||
std::map<string, string> vars;
|
||||
vars[variable1] = value1;
|
||||
vars[variable2] = value2;
|
||||
vars[variable3] = value3;
|
||||
Print(vars, text);
|
||||
}
|
||||
|
||||
void Printer::Print(const char* text,
|
||||
const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3,
|
||||
const char* variable4, const string& value4) {
|
||||
std::map<string, string> vars;
|
||||
vars[variable1] = value1;
|
||||
vars[variable2] = value2;
|
||||
vars[variable3] = value3;
|
||||
vars[variable4] = value4;
|
||||
Print(vars, text);
|
||||
}
|
||||
|
||||
void Printer::Print(const char* text,
|
||||
const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3,
|
||||
const char* variable4, const string& value4,
|
||||
const char* variable5, const string& value5) {
|
||||
std::map<string, string> vars;
|
||||
vars[variable1] = value1;
|
||||
vars[variable2] = value2;
|
||||
vars[variable3] = value3;
|
||||
vars[variable4] = value4;
|
||||
vars[variable5] = value5;
|
||||
Print(vars, text);
|
||||
}
|
||||
|
||||
void Printer::Print(const char* text,
|
||||
const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3,
|
||||
const char* variable4, const string& value4,
|
||||
const char* variable5, const string& value5,
|
||||
const char* variable6, const string& value6) {
|
||||
std::map<string, string> vars;
|
||||
vars[variable1] = value1;
|
||||
vars[variable2] = value2;
|
||||
vars[variable3] = value3;
|
||||
vars[variable4] = value4;
|
||||
vars[variable5] = value5;
|
||||
vars[variable6] = value6;
|
||||
Print(vars, text);
|
||||
}
|
||||
|
||||
void Printer::Print(const char* text,
|
||||
const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3,
|
||||
const char* variable4, const string& value4,
|
||||
const char* variable5, const string& value5,
|
||||
const char* variable6, const string& value6,
|
||||
const char* variable7, const string& value7) {
|
||||
std::map<string, string> vars;
|
||||
vars[variable1] = value1;
|
||||
vars[variable2] = value2;
|
||||
vars[variable3] = value3;
|
||||
vars[variable4] = value4;
|
||||
vars[variable5] = value5;
|
||||
vars[variable6] = value6;
|
||||
vars[variable7] = value7;
|
||||
Print(vars, text);
|
||||
}
|
||||
|
||||
void Printer::Print(const char* text,
|
||||
const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3,
|
||||
const char* variable4, const string& value4,
|
||||
const char* variable5, const string& value5,
|
||||
const char* variable6, const string& value6,
|
||||
const char* variable7, const string& value7,
|
||||
const char* variable8, const string& value8) {
|
||||
std::map<string, string> vars;
|
||||
vars[variable1] = value1;
|
||||
vars[variable2] = value2;
|
||||
vars[variable3] = value3;
|
||||
vars[variable4] = value4;
|
||||
vars[variable5] = value5;
|
||||
vars[variable6] = value6;
|
||||
vars[variable7] = value7;
|
||||
vars[variable8] = value8;
|
||||
Print(vars, text);
|
||||
}
|
||||
|
||||
void Printer::Indent() {
|
||||
indent_ += " ";
|
||||
}
|
||||
|
||||
void Printer::Outdent() {
|
||||
if (indent_.empty()) {
|
||||
GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent().";
|
||||
return;
|
||||
}
|
||||
|
||||
indent_.resize(indent_.size() - 2);
|
||||
}
|
||||
|
||||
void Printer::PrintRaw(const string& data) {
|
||||
WriteRaw(data.data(), data.size());
|
||||
}
|
||||
|
||||
void Printer::PrintRaw(const char* data) {
|
||||
if (failed_) return;
|
||||
WriteRaw(data, strlen(data));
|
||||
}
|
||||
|
||||
void Printer::WriteRaw(const char* data, int size) {
|
||||
if (failed_) return;
|
||||
if (size == 0) return;
|
||||
|
||||
if (at_start_of_line_ && (size > 0) && (data[0] != '\n')) {
|
||||
// Insert an indent.
|
||||
at_start_of_line_ = false;
|
||||
CopyToBuffer(indent_.data(), indent_.size());
|
||||
if (failed_) return;
|
||||
// Fix up empty variables (e.g., "{") that should be annotated as
|
||||
// coming after the indent.
|
||||
for (std::vector<string>::iterator i = line_start_variables_.begin();
|
||||
i != line_start_variables_.end(); ++i) {
|
||||
substitutions_[*i].first += indent_.size();
|
||||
substitutions_[*i].second += indent_.size();
|
||||
}
|
||||
}
|
||||
|
||||
// If we're going to write any data, clear line_start_variables_, since
|
||||
// we've either updated them in the block above or they no longer refer to
|
||||
// the current line.
|
||||
line_start_variables_.clear();
|
||||
|
||||
CopyToBuffer(data, size);
|
||||
}
|
||||
|
||||
void Printer::CopyToBuffer(const char* data, int size) {
|
||||
if (failed_) return;
|
||||
if (size == 0) return;
|
||||
|
||||
while (size > buffer_size_) {
|
||||
// Data exceeds space in the buffer. Copy what we can and request a
|
||||
// new buffer.
|
||||
memcpy(buffer_, data, buffer_size_);
|
||||
offset_ += buffer_size_;
|
||||
data += buffer_size_;
|
||||
size -= buffer_size_;
|
||||
void* void_buffer;
|
||||
failed_ = !output_->Next(&void_buffer, &buffer_size_);
|
||||
if (failed_) return;
|
||||
buffer_ = reinterpret_cast<char*>(void_buffer);
|
||||
}
|
||||
|
||||
// Buffer is big enough to receive the data; copy it.
|
||||
memcpy(buffer_, data, size);
|
||||
buffer_ += size;
|
||||
buffer_size_ -= size;
|
||||
offset_ += size;
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
-363
@@ -1,363 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Utility class for writing text to a ZeroCopyOutputStream.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_PRINTER_H__
|
||||
#define GOOGLE_PROTOBUF_IO_PRINTER_H__
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
class ZeroCopyOutputStream; // zero_copy_stream.h
|
||||
|
||||
// Records annotations about a Printer's output.
|
||||
class LIBPROTOBUF_EXPORT AnnotationCollector {
|
||||
public:
|
||||
// Records that the bytes in file_path beginning with begin_offset and ending
|
||||
// before end_offset are associated with the SourceCodeInfo-style path.
|
||||
virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
|
||||
const string& file_path,
|
||||
const std::vector<int>& path) = 0;
|
||||
|
||||
virtual ~AnnotationCollector() {}
|
||||
};
|
||||
|
||||
// Records annotations about a Printer's output to the given protocol buffer,
|
||||
// assuming that the buffer has an ::Annotation message exposing path,
|
||||
// source_file, begin and end fields.
|
||||
template <typename AnnotationProto>
|
||||
class AnnotationProtoCollector : public AnnotationCollector {
|
||||
public:
|
||||
// annotation_proto is the protocol buffer to which new Annotations should be
|
||||
// added. It is not owned by the AnnotationProtoCollector.
|
||||
explicit AnnotationProtoCollector(AnnotationProto* annotation_proto)
|
||||
: annotation_proto_(annotation_proto) {}
|
||||
|
||||
// Override for AnnotationCollector::AddAnnotation.
|
||||
virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
|
||||
const string& file_path,
|
||||
const std::vector<int>& path) {
|
||||
typename AnnotationProto::Annotation* annotation =
|
||||
annotation_proto_->add_annotation();
|
||||
for (int i = 0; i < path.size(); ++i) {
|
||||
annotation->add_path(path[i]);
|
||||
}
|
||||
annotation->set_source_file(file_path);
|
||||
annotation->set_begin(begin_offset);
|
||||
annotation->set_end(end_offset);
|
||||
}
|
||||
|
||||
private:
|
||||
// The protocol buffer to which new annotations should be added.
|
||||
AnnotationProto* const annotation_proto_;
|
||||
};
|
||||
|
||||
// This simple utility class assists in code generation. It basically
|
||||
// allows the caller to define a set of variables and then output some
|
||||
// text with variable substitutions. Example usage:
|
||||
//
|
||||
// Printer printer(output, '$');
|
||||
// map<string, string> vars;
|
||||
// vars["name"] = "Bob";
|
||||
// printer.Print(vars, "My name is $name$.");
|
||||
//
|
||||
// The above writes "My name is Bob." to the output stream.
|
||||
//
|
||||
// Printer aggressively enforces correct usage, crashing (with assert failures)
|
||||
// in the case of undefined variables in debug builds. This helps greatly in
|
||||
// debugging code which uses it.
|
||||
//
|
||||
// If a Printer is constructed with an AnnotationCollector, it will provide it
|
||||
// with annotations that connect the Printer's output to paths that can identify
|
||||
// various descriptors. In the above example, if person_ is a descriptor that
|
||||
// identifies Bob, we can associate the output string "My name is Bob." with
|
||||
// a source path pointing to that descriptor with:
|
||||
//
|
||||
// printer.Annotate("name", person_);
|
||||
//
|
||||
// The AnnotationCollector will be sent an annotation linking the output range
|
||||
// covering "Bob" to the logical path provided by person_. Tools may use
|
||||
// this association to (for example) link "Bob" in the output back to the
|
||||
// source file that defined the person_ descriptor identifying Bob.
|
||||
//
|
||||
// Annotate can only examine variables substituted during the last call to
|
||||
// Print. It is invalid to refer to a variable that was used multiple times
|
||||
// in a single Print call.
|
||||
//
|
||||
// In full generality, one may specify a range of output text using a beginning
|
||||
// substitution variable and an ending variable. The resulting annotation will
|
||||
// span from the first character of the substituted value for the beginning
|
||||
// variable to the last character of the substituted value for the ending
|
||||
// variable. For example, the Annotate call above is equivalent to this one:
|
||||
//
|
||||
// printer.Annotate("name", "name", person_);
|
||||
//
|
||||
// This is useful if multiple variables combine to form a single span of output
|
||||
// that should be annotated with the same source path. For example:
|
||||
//
|
||||
// Printer printer(output, '$');
|
||||
// map<string, string> vars;
|
||||
// vars["first"] = "Alice";
|
||||
// vars["last"] = "Smith";
|
||||
// printer.Print(vars, "My name is $first$ $last$.");
|
||||
// printer.Annotate("first", "last", person_);
|
||||
//
|
||||
// This code would associate the span covering "Alice Smith" in the output with
|
||||
// the person_ descriptor.
|
||||
//
|
||||
// Note that the beginning variable must come before (or overlap with, in the
|
||||
// case of zero-sized substitution values) the ending variable.
|
||||
//
|
||||
// It is also sometimes useful to use variables with zero-sized values as
|
||||
// markers. This avoids issues with multiple references to the same variable
|
||||
// and also allows annotation ranges to span literal text from the Print
|
||||
// templates:
|
||||
//
|
||||
// Printer printer(output, '$');
|
||||
// map<string, string> vars;
|
||||
// vars["foo"] = "bar";
|
||||
// vars["function"] = "call";
|
||||
// vars["mark"] = "";
|
||||
// printer.Print(vars, "$function$($foo$,$foo$)$mark$");
|
||||
// printer.Annotate("function", "mark", call_);
|
||||
//
|
||||
// This code associates the span covering "call(bar,bar)" in the output with the
|
||||
// call_ descriptor.
|
||||
|
||||
class LIBPROTOBUF_EXPORT Printer {
|
||||
public:
|
||||
// Create a printer that writes text to the given output stream. Use the
|
||||
// given character as the delimiter for variables.
|
||||
Printer(ZeroCopyOutputStream* output, char variable_delimiter);
|
||||
|
||||
// Create a printer that writes text to the given output stream. Use the
|
||||
// given character as the delimiter for variables. If annotation_collector
|
||||
// is not null, Printer will provide it with annotations about code written
|
||||
// to the stream. annotation_collector is not owned by Printer.
|
||||
Printer(ZeroCopyOutputStream* output, char variable_delimiter,
|
||||
AnnotationCollector* annotation_collector);
|
||||
|
||||
~Printer();
|
||||
|
||||
// Link a subsitution variable emitted by the last call to Print to the object
|
||||
// described by descriptor.
|
||||
template <typename SomeDescriptor>
|
||||
void Annotate(const char* varname, const SomeDescriptor* descriptor) {
|
||||
Annotate(varname, varname, descriptor);
|
||||
}
|
||||
|
||||
// Link the output range defined by the substitution variables as emitted by
|
||||
// the last call to Print to the object described by descriptor. The range
|
||||
// begins at begin_varname's value and ends after the last character of the
|
||||
// value substituted for end_varname.
|
||||
template <typename SomeDescriptor>
|
||||
void Annotate(const char* begin_varname, const char* end_varname,
|
||||
const SomeDescriptor* descriptor) {
|
||||
if (annotation_collector_ == NULL) {
|
||||
// Annotations aren't turned on for this Printer, so don't pay the cost
|
||||
// of building the location path.
|
||||
return;
|
||||
}
|
||||
std::vector<int> path;
|
||||
descriptor->GetLocationPath(&path);
|
||||
Annotate(begin_varname, end_varname, descriptor->file()->name(), path);
|
||||
}
|
||||
|
||||
// Link a subsitution variable emitted by the last call to Print to the file
|
||||
// with path file_name.
|
||||
void Annotate(const char* varname, const string& file_name) {
|
||||
Annotate(varname, varname, file_name);
|
||||
}
|
||||
|
||||
// Link the output range defined by the substitution variables as emitted by
|
||||
// the last call to Print to the file with path file_name. The range begins
|
||||
// at begin_varname's value and ends after the last character of the value
|
||||
// substituted for end_varname.
|
||||
void Annotate(const char* begin_varname, const char* end_varname,
|
||||
const string& file_name) {
|
||||
if (annotation_collector_ == NULL) {
|
||||
// Annotations aren't turned on for this Printer.
|
||||
return;
|
||||
}
|
||||
std::vector<int> empty_path;
|
||||
Annotate(begin_varname, end_varname, file_name, empty_path);
|
||||
}
|
||||
|
||||
// Print some text after applying variable substitutions. If a particular
|
||||
// variable in the text is not defined, this will crash. Variables to be
|
||||
// substituted are identified by their names surrounded by delimiter
|
||||
// characters (as given to the constructor). The variable bindings are
|
||||
// defined by the given map.
|
||||
void Print(const std::map<string, string>& variables, const char* text);
|
||||
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text);
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text, const char* variable, const string& value);
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text, const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2);
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text, const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3);
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text, const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3,
|
||||
const char* variable4, const string& value4);
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text, const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3,
|
||||
const char* variable4, const string& value4,
|
||||
const char* variable5, const string& value5);
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text, const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3,
|
||||
const char* variable4, const string& value4,
|
||||
const char* variable5, const string& value5,
|
||||
const char* variable6, const string& value6);
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text, const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3,
|
||||
const char* variable4, const string& value4,
|
||||
const char* variable5, const string& value5,
|
||||
const char* variable6, const string& value6,
|
||||
const char* variable7, const string& value7);
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text, const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3,
|
||||
const char* variable4, const string& value4,
|
||||
const char* variable5, const string& value5,
|
||||
const char* variable6, const string& value6,
|
||||
const char* variable7, const string& value7,
|
||||
const char* variable8, const string& value8);
|
||||
|
||||
// Indent text by two spaces. After calling Indent(), two spaces will be
|
||||
// inserted at the beginning of each line of text. Indent() may be called
|
||||
// multiple times to produce deeper indents.
|
||||
void Indent();
|
||||
|
||||
// Reduces the current indent level by two spaces, or crashes if the indent
|
||||
// level is zero.
|
||||
void Outdent();
|
||||
|
||||
// Write a string to the output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void PrintRaw(const string& data);
|
||||
|
||||
// Write a zero-delimited string to output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void PrintRaw(const char* data);
|
||||
|
||||
// Write some bytes to the output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void WriteRaw(const char* data, int size);
|
||||
|
||||
// True if any write to the underlying stream failed. (We don't just
|
||||
// crash in this case because this is an I/O failure, not a programming
|
||||
// error.)
|
||||
bool failed() const { return failed_; }
|
||||
|
||||
private:
|
||||
// Link the output range defined by the substitution variables as emitted by
|
||||
// the last call to Print to the object found at the SourceCodeInfo-style path
|
||||
// in a file with path file_path. The range begins at the start of
|
||||
// begin_varname's value and ends after the last character of the value
|
||||
// substituted for end_varname. Note that begin_varname and end_varname
|
||||
// may refer to the same variable.
|
||||
void Annotate(const char* begin_varname, const char* end_varname,
|
||||
const string& file_path, const std::vector<int>& path);
|
||||
|
||||
// Copy size worth of bytes from data to buffer_.
|
||||
void CopyToBuffer(const char* data, int size);
|
||||
|
||||
const char variable_delimiter_;
|
||||
|
||||
ZeroCopyOutputStream* const output_;
|
||||
char* buffer_;
|
||||
int buffer_size_;
|
||||
// The current position, in bytes, in the output stream. This is equivalent
|
||||
// to the total number of bytes that have been written so far. This value is
|
||||
// used to calculate annotation ranges in the substitutions_ map below.
|
||||
size_t offset_;
|
||||
|
||||
string indent_;
|
||||
bool at_start_of_line_;
|
||||
bool failed_;
|
||||
|
||||
// A map from variable name to [start, end) offsets in the output buffer.
|
||||
// These refer to the offsets used for a variable after the last call to
|
||||
// Print. If a variable was used more than once, the entry used in
|
||||
// this map is set to a negative-length span. For singly-used variables, the
|
||||
// start offset is the beginning of the substitution; the end offset is the
|
||||
// last byte of the substitution plus one (such that (end - start) is the
|
||||
// length of the substituted string).
|
||||
std::map<string, std::pair<size_t, size_t> > substitutions_;
|
||||
|
||||
// Keeps track of the keys in substitutions_ that need to be updated when
|
||||
// indents are inserted. These are keys that refer to the beginning of the
|
||||
// current line.
|
||||
std::vector<string> line_start_variables_;
|
||||
|
||||
// Returns true and sets range to the substitution range in the output for
|
||||
// varname if varname was used once in the last call to Print. If varname
|
||||
// was not used, or if it was used multiple times, returns false (and
|
||||
// fails a debug assertion).
|
||||
bool GetSubstitutionRange(const char* varname,
|
||||
std::pair<size_t, size_t>* range);
|
||||
|
||||
// If non-null, annotation_collector_ is used to store annotations about
|
||||
// generated code.
|
||||
AnnotationCollector* const annotation_collector_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Printer);
|
||||
};
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_PRINTER_H__
|
||||
+24
-67
@@ -38,88 +38,45 @@
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// NoLocaleStrtod()
|
||||
// This code will make you cry.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
|
||||
// Returns a string identical to *input except that the character pointed to
|
||||
// by radix_pos (which should be '.') is replaced with the locale-specific
|
||||
// radix character.
|
||||
string LocalizeRadix(const char* input, const char* radix_pos) {
|
||||
// Determine the locale-specific radix character by calling sprintf() to
|
||||
// print the number 1.5, then stripping off the digits. As far as I can
|
||||
// tell, this is the only portable, thread-safe way to get the C library
|
||||
// to divuldge the locale's radix character. No, localeconv() is NOT
|
||||
// thread-safe.
|
||||
char temp[16];
|
||||
int size = sprintf(temp, "%.1f", 1.5);
|
||||
GOOGLE_CHECK_EQ(temp[0], '1');
|
||||
GOOGLE_CHECK_EQ(temp[size-1], '5');
|
||||
GOOGLE_CHECK_LE(size, 6);
|
||||
|
||||
// Now replace the '.' in the input with it.
|
||||
string result;
|
||||
result.reserve(strlen(input) + size - 3);
|
||||
result.append(input, radix_pos);
|
||||
result.append(temp + 1, size - 2);
|
||||
result.append(radix_pos + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
double NoLocaleStrtod(const char* text, char** original_endptr) {
|
||||
// We cannot simply set the locale to "C" temporarily with setlocale()
|
||||
// as this is not thread-safe. Instead, we try to parse in the current
|
||||
// locale first. If parsing stops at a '.' character, then this is a
|
||||
// pretty good hint that we're actually in some other locale in which
|
||||
// '.' is not the radix character.
|
||||
|
||||
char* temp_endptr;
|
||||
double result = strtod(text, &temp_endptr);
|
||||
if (original_endptr != NULL) *original_endptr = temp_endptr;
|
||||
if (*temp_endptr != '.') return result;
|
||||
|
||||
// Parsing halted on a '.'. Perhaps we're in a different locale? Let's
|
||||
// try to replace the '.' with a locale-specific radix character and
|
||||
// try again.
|
||||
string localized = LocalizeRadix(text, temp_endptr);
|
||||
const char* localized_cstr = localized.c_str();
|
||||
char* localized_endptr;
|
||||
result = strtod(localized_cstr, &localized_endptr);
|
||||
if ((localized_endptr - localized_cstr) >
|
||||
(temp_endptr - text)) {
|
||||
// This attempt got further, so replacing the decimal must have helped.
|
||||
// Update original_endptr to point at the right location.
|
||||
if (original_endptr != NULL) {
|
||||
// size_diff is non-zero if the localized radix has multiple bytes.
|
||||
int size_diff = localized.size() - strlen(text);
|
||||
// const_cast is necessary to match the strtod() interface.
|
||||
*original_endptr = const_cast<char*>(
|
||||
text + (localized_endptr - localized_cstr - size_diff));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
// This approximately 0x1.ffffffp127, but we don't use 0x1.ffffffp127 because
|
||||
// it won't compile in MSVC.
|
||||
const double MAX_FLOAT_AS_DOUBLE_ROUNDED = 3.4028235677973366e+38;
|
||||
|
||||
float SafeDoubleToFloat(double value) {
|
||||
// static_cast<float> on a number larger than float can result in illegal
|
||||
// instruction error, so we need to manually convert it to infinity or max.
|
||||
if (value > std::numeric_limits<float>::max()) {
|
||||
// Max float value is about 3.4028234664E38 when represented as a double.
|
||||
// However, when printing float as text, it will be rounded as
|
||||
// 3.4028235e+38. If we parse the value of 3.4028235e+38 from text and
|
||||
// compare it to 3.4028234664E38, we may think that it is larger, but
|
||||
// actually, any number between these two numbers could only be represented
|
||||
// as the same max float number in float, so we should treat them the same
|
||||
// as max float.
|
||||
if (value <= MAX_FLOAT_AS_DOUBLE_ROUNDED) {
|
||||
return std::numeric_limits<float>::max();
|
||||
}
|
||||
return std::numeric_limits<float>::infinity();
|
||||
} else if (value < -std::numeric_limits<float>::max()) {
|
||||
if (value >= -MAX_FLOAT_AS_DOUBLE_ROUNDED) {
|
||||
return -std::numeric_limits<float>::max();
|
||||
}
|
||||
return -std::numeric_limits<float>::infinity();
|
||||
} else {
|
||||
return static_cast<float>(value);
|
||||
}
|
||||
}
|
||||
|
||||
double NoLocaleStrtod(const char* str, char** endptr) {
|
||||
return google::protobuf::internal::NoLocaleStrtod(str, endptr);
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
+1
-1
@@ -50,6 +50,6 @@ float SafeDoubleToFloat(double value);
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_STRTOD_H__
|
||||
|
||||
+210
-164
@@ -89,12 +89,13 @@
|
||||
// exactly pretty.
|
||||
|
||||
#include <google/protobuf/io/tokenizer.h>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/stringprintf.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/io/strtod.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
namespace google {
|
||||
@@ -113,39 +114,34 @@ namespace {
|
||||
// Note: No class is allowed to contain '\0', since this is used to mark end-
|
||||
// of-input and is handled specially.
|
||||
|
||||
#define CHARACTER_CLASS(NAME, EXPRESSION) \
|
||||
class NAME { \
|
||||
public: \
|
||||
static inline bool InClass(char c) { \
|
||||
return EXPRESSION; \
|
||||
} \
|
||||
#define CHARACTER_CLASS(NAME, EXPRESSION) \
|
||||
class NAME { \
|
||||
public: \
|
||||
static inline bool InClass(char c) { return EXPRESSION; } \
|
||||
}
|
||||
|
||||
CHARACTER_CLASS(Whitespace, c == ' ' || c == '\n' || c == '\t' ||
|
||||
c == '\r' || c == '\v' || c == '\f');
|
||||
CHARACTER_CLASS(WhitespaceNoNewline, c == ' ' || c == '\t' ||
|
||||
c == '\r' || c == '\v' || c == '\f');
|
||||
CHARACTER_CLASS(Whitespace, c == ' ' || c == '\n' || c == '\t' || c == '\r' ||
|
||||
c == '\v' || c == '\f');
|
||||
CHARACTER_CLASS(WhitespaceNoNewline,
|
||||
c == ' ' || c == '\t' || c == '\r' || c == '\v' || c == '\f');
|
||||
|
||||
CHARACTER_CLASS(Unprintable, c < ' ' && c > '\0');
|
||||
CHARACTER_CLASS(Unprintable, c<' ' && c> '\0');
|
||||
|
||||
CHARACTER_CLASS(Digit, '0' <= c && c <= '9');
|
||||
CHARACTER_CLASS(OctalDigit, '0' <= c && c <= '7');
|
||||
CHARACTER_CLASS(HexDigit, ('0' <= c && c <= '9') ||
|
||||
('a' <= c && c <= 'f') ||
|
||||
('A' <= c && c <= 'F'));
|
||||
CHARACTER_CLASS(HexDigit, ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') ||
|
||||
('A' <= c && c <= 'F'));
|
||||
|
||||
CHARACTER_CLASS(Letter, ('a' <= c && c <= 'z') ||
|
||||
('A' <= c && c <= 'Z') ||
|
||||
(c == '_'));
|
||||
CHARACTER_CLASS(Letter,
|
||||
('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '_'));
|
||||
|
||||
CHARACTER_CLASS(Alphanumeric, ('a' <= c && c <= 'z') ||
|
||||
('A' <= c && c <= 'Z') ||
|
||||
('0' <= c && c <= '9') ||
|
||||
(c == '_'));
|
||||
('A' <= c && c <= 'Z') ||
|
||||
('0' <= c && c <= '9') || (c == '_'));
|
||||
|
||||
CHARACTER_CLASS(Escape, c == 'a' || c == 'b' || c == 'f' || c == 'n' ||
|
||||
c == 'r' || c == 't' || c == 'v' || c == '\\' ||
|
||||
c == '?' || c == '\'' || c == '\"');
|
||||
c == 'r' || c == 't' || c == 'v' || c == '\\' ||
|
||||
c == '?' || c == '\'' || c == '\"');
|
||||
|
||||
#undef CHARACTER_CLASS
|
||||
|
||||
@@ -161,20 +157,32 @@ inline int DigitValue(char digit) {
|
||||
// Inline because it's only used in one place.
|
||||
inline char TranslateEscape(char c) {
|
||||
switch (c) {
|
||||
case 'a': return '\a';
|
||||
case 'b': return '\b';
|
||||
case 'f': return '\f';
|
||||
case 'n': return '\n';
|
||||
case 'r': return '\r';
|
||||
case 't': return '\t';
|
||||
case 'v': return '\v';
|
||||
case '\\': return '\\';
|
||||
case '?': return '\?'; // Trigraphs = :(
|
||||
case '\'': return '\'';
|
||||
case '"': return '\"';
|
||||
case 'a':
|
||||
return '\a';
|
||||
case 'b':
|
||||
return '\b';
|
||||
case 'f':
|
||||
return '\f';
|
||||
case 'n':
|
||||
return '\n';
|
||||
case 'r':
|
||||
return '\r';
|
||||
case 't':
|
||||
return '\t';
|
||||
case 'v':
|
||||
return '\v';
|
||||
case '\\':
|
||||
return '\\';
|
||||
case '?':
|
||||
return '\?'; // Trigraphs = :(
|
||||
case '\'':
|
||||
return '\'';
|
||||
case '"':
|
||||
return '\"';
|
||||
|
||||
// We expect escape sequences to have been validated separately.
|
||||
default: return '?';
|
||||
default:
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,21 +194,20 @@ ErrorCollector::~ErrorCollector() {}
|
||||
|
||||
Tokenizer::Tokenizer(ZeroCopyInputStream* input,
|
||||
ErrorCollector* error_collector)
|
||||
: input_(input),
|
||||
error_collector_(error_collector),
|
||||
buffer_(NULL),
|
||||
buffer_size_(0),
|
||||
buffer_pos_(0),
|
||||
read_error_(false),
|
||||
line_(0),
|
||||
column_(0),
|
||||
record_target_(NULL),
|
||||
record_start_(-1),
|
||||
allow_f_after_float_(false),
|
||||
comment_style_(CPP_COMMENT_STYLE),
|
||||
require_space_after_number_(true),
|
||||
allow_multiline_strings_(false) {
|
||||
|
||||
: input_(input),
|
||||
error_collector_(error_collector),
|
||||
buffer_(NULL),
|
||||
buffer_size_(0),
|
||||
buffer_pos_(0),
|
||||
read_error_(false),
|
||||
line_(0),
|
||||
column_(0),
|
||||
record_target_(NULL),
|
||||
record_start_(-1),
|
||||
allow_f_after_float_(false),
|
||||
comment_style_(CPP_COMMENT_STYLE),
|
||||
require_space_after_number_(true),
|
||||
allow_multiline_strings_(false) {
|
||||
current_.line = 0;
|
||||
current_.column = 0;
|
||||
current_.end_column = 0;
|
||||
@@ -217,6 +224,21 @@ Tokenizer::~Tokenizer() {
|
||||
}
|
||||
}
|
||||
|
||||
bool Tokenizer::report_whitespace() const { return report_whitespace_; }
|
||||
// Note: `set_report_whitespace(false)` implies `set_report_newlines(false)`.
|
||||
void Tokenizer::set_report_whitespace(bool report) {
|
||||
report_whitespace_ = report;
|
||||
report_newlines_ &= report;
|
||||
}
|
||||
|
||||
// If true, newline tokens are reported by Next().
|
||||
bool Tokenizer::report_newlines() const { return report_newlines_; }
|
||||
// Note: `set_report_newlines(true)` implies `set_report_whitespace(true)`.
|
||||
void Tokenizer::set_report_newlines(bool report) {
|
||||
report_newlines_ = report;
|
||||
report_whitespace_ |= report; // enable report_whitespace if necessary
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Internal helpers.
|
||||
|
||||
@@ -249,7 +271,8 @@ void Tokenizer::Refresh() {
|
||||
|
||||
// If we're in a token, append the rest of the buffer to it.
|
||||
if (record_target_ != NULL && record_start_ < buffer_size_) {
|
||||
record_target_->append(buffer_ + record_start_, buffer_size_ - record_start_);
|
||||
record_target_->append(buffer_ + record_start_,
|
||||
buffer_size_ - record_start_);
|
||||
record_start_ = 0;
|
||||
}
|
||||
|
||||
@@ -271,7 +294,7 @@ void Tokenizer::Refresh() {
|
||||
current_char_ = buffer_[0];
|
||||
}
|
||||
|
||||
inline void Tokenizer::RecordTo(string* target) {
|
||||
inline void Tokenizer::RecordTo(std::string* target) {
|
||||
record_target_ = target;
|
||||
record_start_ = buffer_pos_;
|
||||
}
|
||||
@@ -282,14 +305,15 @@ inline void Tokenizer::StopRecording() {
|
||||
// be helpful by detecting the NULL pointer, even though there's nothing
|
||||
// wrong with reading zero bytes from NULL.
|
||||
if (buffer_pos_ != record_start_) {
|
||||
record_target_->append(buffer_ + record_start_, buffer_pos_ - record_start_);
|
||||
record_target_->append(buffer_ + record_start_,
|
||||
buffer_pos_ - record_start_);
|
||||
}
|
||||
record_target_ = NULL;
|
||||
record_start_ = -1;
|
||||
}
|
||||
|
||||
inline void Tokenizer::StartToken() {
|
||||
current_.type = TYPE_START; // Just for the sake of initializing it.
|
||||
current_.type = TYPE_START; // Just for the sake of initializing it.
|
||||
current_.text.clear();
|
||||
current_.line = line_;
|
||||
current_.column = column_;
|
||||
@@ -304,12 +328,12 @@ inline void Tokenizer::EndToken() {
|
||||
// -------------------------------------------------------------------
|
||||
// Helper methods that consume characters.
|
||||
|
||||
template<typename CharacterClass>
|
||||
template <typename CharacterClass>
|
||||
inline bool Tokenizer::LookingAt() {
|
||||
return CharacterClass::InClass(current_char_);
|
||||
}
|
||||
|
||||
template<typename CharacterClass>
|
||||
template <typename CharacterClass>
|
||||
inline bool Tokenizer::TryConsumeOne() {
|
||||
if (CharacterClass::InClass(current_char_)) {
|
||||
NextChar();
|
||||
@@ -328,14 +352,14 @@ inline bool Tokenizer::TryConsume(char c) {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename CharacterClass>
|
||||
template <typename CharacterClass>
|
||||
inline void Tokenizer::ConsumeZeroOrMore() {
|
||||
while (CharacterClass::InClass(current_char_)) {
|
||||
NextChar();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename CharacterClass>
|
||||
template <typename CharacterClass>
|
||||
inline void Tokenizer::ConsumeOneOrMore(const char* error) {
|
||||
if (!CharacterClass::InClass(current_char_)) {
|
||||
AddError(error);
|
||||
@@ -381,25 +405,21 @@ void Tokenizer::ConsumeString(char delimiter) {
|
||||
}
|
||||
// Possibly followed by another hex digit, but again we don't care.
|
||||
} else if (TryConsume('u')) {
|
||||
if (!TryConsumeOne<HexDigit>() ||
|
||||
!TryConsumeOne<HexDigit>() ||
|
||||
!TryConsumeOne<HexDigit>() ||
|
||||
!TryConsumeOne<HexDigit>()) {
|
||||
if (!TryConsumeOne<HexDigit>() || !TryConsumeOne<HexDigit>() ||
|
||||
!TryConsumeOne<HexDigit>() || !TryConsumeOne<HexDigit>()) {
|
||||
AddError("Expected four hex digits for \\u escape sequence.");
|
||||
}
|
||||
} else if (TryConsume('U')) {
|
||||
// We expect 8 hex digits; but only the range up to 0x10ffff is
|
||||
// legal.
|
||||
if (!TryConsume('0') ||
|
||||
!TryConsume('0') ||
|
||||
if (!TryConsume('0') || !TryConsume('0') ||
|
||||
!(TryConsume('0') || TryConsume('1')) ||
|
||||
!TryConsumeOne<HexDigit>() ||
|
||||
!TryConsumeOne<HexDigit>() ||
|
||||
!TryConsumeOne<HexDigit>() ||
|
||||
!TryConsumeOne<HexDigit>() ||
|
||||
!TryConsumeOne<HexDigit>() || !TryConsumeOne<HexDigit>() ||
|
||||
!TryConsumeOne<HexDigit>() || !TryConsumeOne<HexDigit>() ||
|
||||
!TryConsumeOne<HexDigit>()) {
|
||||
AddError("Expected eight hex digits up to 10ffff for \\U escape "
|
||||
"sequence");
|
||||
AddError(
|
||||
"Expected eight hex digits up to 10ffff for \\U escape "
|
||||
"sequence");
|
||||
}
|
||||
} else {
|
||||
AddError("Invalid escape sequence in string literal.");
|
||||
@@ -465,7 +485,7 @@ Tokenizer::TokenType Tokenizer::ConsumeNumber(bool started_with_zero,
|
||||
} else if (current_char_ == '.') {
|
||||
if (is_float) {
|
||||
AddError(
|
||||
"Already saw decimal point or exponent; can't have another one.");
|
||||
"Already saw decimal point or exponent; can't have another one.");
|
||||
} else {
|
||||
AddError("Hex and octal numbers must be integers.");
|
||||
}
|
||||
@@ -474,7 +494,7 @@ Tokenizer::TokenType Tokenizer::ConsumeNumber(bool started_with_zero,
|
||||
return is_float ? TYPE_FLOAT : TYPE_INTEGER;
|
||||
}
|
||||
|
||||
void Tokenizer::ConsumeLineComment(string* content) {
|
||||
void Tokenizer::ConsumeLineComment(std::string* content) {
|
||||
if (content != NULL) RecordTo(content);
|
||||
|
||||
while (current_char_ != '\0' && current_char_ != '\n') {
|
||||
@@ -485,17 +505,15 @@ void Tokenizer::ConsumeLineComment(string* content) {
|
||||
if (content != NULL) StopRecording();
|
||||
}
|
||||
|
||||
void Tokenizer::ConsumeBlockComment(string* content) {
|
||||
void Tokenizer::ConsumeBlockComment(std::string* content) {
|
||||
int start_line = line_;
|
||||
int start_column = column_ - 2;
|
||||
|
||||
if (content != NULL) RecordTo(content);
|
||||
|
||||
while (true) {
|
||||
while (current_char_ != '\0' &&
|
||||
current_char_ != '*' &&
|
||||
current_char_ != '/' &&
|
||||
current_char_ != '\n') {
|
||||
while (current_char_ != '\0' && current_char_ != '*' &&
|
||||
current_char_ != '/' && current_char_ != '\n') {
|
||||
NextChar();
|
||||
}
|
||||
|
||||
@@ -524,11 +542,11 @@ void Tokenizer::ConsumeBlockComment(string* content) {
|
||||
// Note: We didn't consume the '*' because if there is a '/' after it
|
||||
// we want to interpret that as the end of the comment.
|
||||
AddError(
|
||||
"\"/*\" inside block comment. Block comments cannot be nested.");
|
||||
"\"/*\" inside block comment. Block comments cannot be nested.");
|
||||
} else if (current_char_ == '\0') {
|
||||
AddError("End-of-file inside block comment.");
|
||||
error_collector_->AddError(
|
||||
start_line, start_column, " Comment started here.");
|
||||
error_collector_->AddError(start_line, start_column,
|
||||
" Comment started here.");
|
||||
if (content != NULL) StopRecording();
|
||||
break;
|
||||
}
|
||||
@@ -557,13 +575,46 @@ Tokenizer::NextCommentStatus Tokenizer::TryConsumeCommentStart() {
|
||||
}
|
||||
}
|
||||
|
||||
bool Tokenizer::TryConsumeWhitespace() {
|
||||
if (report_newlines_) {
|
||||
if (TryConsumeOne<WhitespaceNoNewline>()) {
|
||||
ConsumeZeroOrMore<WhitespaceNoNewline>();
|
||||
current_.type = TYPE_WHITESPACE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (TryConsumeOne<Whitespace>()) {
|
||||
ConsumeZeroOrMore<Whitespace>();
|
||||
current_.type = TYPE_WHITESPACE;
|
||||
return report_whitespace_;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Tokenizer::TryConsumeNewline() {
|
||||
if (!report_whitespace_ || !report_newlines_) {
|
||||
return false;
|
||||
}
|
||||
if (TryConsume('\n')) {
|
||||
current_.type = TYPE_NEWLINE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
bool Tokenizer::Next() {
|
||||
previous_ = current_;
|
||||
|
||||
while (!read_error_) {
|
||||
ConsumeZeroOrMore<Whitespace>();
|
||||
StartToken();
|
||||
bool report_token = TryConsumeWhitespace() || TryConsumeNewline();
|
||||
EndToken();
|
||||
if (report_token) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (TryConsumeCommentStart()) {
|
||||
case LINE_COMMENT:
|
||||
@@ -613,8 +664,9 @@ bool Tokenizer::Next() {
|
||||
current_.line == previous_.line &&
|
||||
current_.column == previous_.end_column) {
|
||||
// We don't accept syntax like "blah.123".
|
||||
error_collector_->AddError(line_, column_ - 2,
|
||||
"Need space between identifier and decimal point.");
|
||||
error_collector_->AddError(
|
||||
line_, column_ - 2,
|
||||
"Need space between identifier and decimal point.");
|
||||
}
|
||||
current_.type = ConsumeNumber(false, true);
|
||||
} else {
|
||||
@@ -631,7 +683,8 @@ bool Tokenizer::Next() {
|
||||
} else {
|
||||
// Check if the high order bit is set.
|
||||
if (current_char_ & 0x80) {
|
||||
error_collector_->AddError(line_, column_,
|
||||
error_collector_->AddError(
|
||||
line_, column_,
|
||||
StringPrintf("Interpreting non ascii codepoint %d.",
|
||||
static_cast<unsigned char>(current_char_)));
|
||||
}
|
||||
@@ -664,9 +717,9 @@ namespace {
|
||||
// next_leading_comments.
|
||||
class CommentCollector {
|
||||
public:
|
||||
CommentCollector(string* prev_trailing_comments,
|
||||
std::vector<string>* detached_comments,
|
||||
string* next_leading_comments)
|
||||
CommentCollector(std::string* prev_trailing_comments,
|
||||
std::vector<std::string>* detached_comments,
|
||||
std::string* next_leading_comments)
|
||||
: prev_trailing_comments_(prev_trailing_comments),
|
||||
detached_comments_(detached_comments),
|
||||
next_leading_comments_(next_leading_comments),
|
||||
@@ -687,7 +740,7 @@ class CommentCollector {
|
||||
|
||||
// About to read a line comment. Get the comment buffer pointer in order to
|
||||
// read into it.
|
||||
string* GetBufferForLineComment() {
|
||||
std::string* GetBufferForLineComment() {
|
||||
// We want to combine with previous line comments, but not block comments.
|
||||
if (has_comment_ && !is_line_comment_) {
|
||||
Flush();
|
||||
@@ -699,7 +752,7 @@ class CommentCollector {
|
||||
|
||||
// About to read a block comment. Get the comment buffer pointer in order to
|
||||
// read into it.
|
||||
string* GetBufferForBlockComment() {
|
||||
std::string* GetBufferForBlockComment() {
|
||||
if (has_comment_) {
|
||||
Flush();
|
||||
}
|
||||
@@ -731,16 +784,14 @@ class CommentCollector {
|
||||
}
|
||||
}
|
||||
|
||||
void DetachFromPrev() {
|
||||
can_attach_to_prev_ = false;
|
||||
}
|
||||
void DetachFromPrev() { can_attach_to_prev_ = false; }
|
||||
|
||||
private:
|
||||
string* prev_trailing_comments_;
|
||||
std::vector<string>* detached_comments_;
|
||||
string* next_leading_comments_;
|
||||
std::string* prev_trailing_comments_;
|
||||
std::vector<std::string>* detached_comments_;
|
||||
std::string* next_leading_comments_;
|
||||
|
||||
string comment_buffer_;
|
||||
std::string comment_buffer_;
|
||||
|
||||
// True if any comments were read into comment_buffer_. This can be true even
|
||||
// if comment_buffer_ is empty, namely if the comment was "/**/".
|
||||
@@ -754,21 +805,23 @@ class CommentCollector {
|
||||
bool can_attach_to_prev_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
bool Tokenizer::NextWithComments(string* prev_trailing_comments,
|
||||
std::vector<string>* detached_comments,
|
||||
string* next_leading_comments) {
|
||||
bool Tokenizer::NextWithComments(std::string* prev_trailing_comments,
|
||||
std::vector<std::string>* detached_comments,
|
||||
std::string* next_leading_comments) {
|
||||
CommentCollector collector(prev_trailing_comments, detached_comments,
|
||||
next_leading_comments);
|
||||
|
||||
if (current_.type == TYPE_START) {
|
||||
// Ignore unicode byte order mark(BOM) if it appears at the file
|
||||
// beginning. Only UTF-8 BOM (0xEF 0xBB 0xBF) is accepted.
|
||||
if (TryConsume((char)0xEF)) {
|
||||
if (!TryConsume((char)0xBB) || !TryConsume((char)0xBF)) {
|
||||
AddError("Proto file starts with 0xEF but not UTF-8 BOM. "
|
||||
"Only UTF-8 is accepted for proto file.");
|
||||
if (TryConsume(static_cast<char>(0xEF))) {
|
||||
if (!TryConsume(static_cast<char>(0xBB)) ||
|
||||
!TryConsume(static_cast<char>(0xBF))) {
|
||||
AddError(
|
||||
"Proto file starts with 0xEF but not UTF-8 BOM. "
|
||||
"Only UTF-8 is accepted for proto file.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -836,9 +889,7 @@ bool Tokenizer::NextWithComments(string* prev_trailing_comments,
|
||||
collector.DetachFromPrev();
|
||||
} else {
|
||||
bool result = Next();
|
||||
if (!result ||
|
||||
current_.text == "}" ||
|
||||
current_.text == "]" ||
|
||||
if (!result || current_.text == "}" || current_.text == "]" ||
|
||||
current_.text == ")") {
|
||||
// It looks like we're at the end of a scope. In this case it
|
||||
// makes no sense to attach a comment to the following token.
|
||||
@@ -858,12 +909,12 @@ bool Tokenizer::NextWithComments(string* prev_trailing_comments,
|
||||
// are given is text that the tokenizer actually parsed as a token
|
||||
// of the given type.
|
||||
|
||||
bool Tokenizer::ParseInteger(const string& text, uint64 max_value,
|
||||
uint64* output) {
|
||||
bool Tokenizer::ParseInteger(const std::string& text, uint64_t max_value,
|
||||
uint64_t* output) {
|
||||
// Sadly, we can't just use strtoul() since it is only 32-bit and strtoull()
|
||||
// is non-standard. I hate the C standard library. :(
|
||||
|
||||
// return strtoull(text.c_str(), NULL, 0);
|
||||
// return strtoull(text.c_str(), NULL, 0);
|
||||
|
||||
const char* ptr = text.c_str();
|
||||
int base = 10;
|
||||
@@ -878,7 +929,7 @@ bool Tokenizer::ParseInteger(const string& text, uint64 max_value,
|
||||
}
|
||||
}
|
||||
|
||||
uint64 result = 0;
|
||||
uint64_t result = 0;
|
||||
for (; *ptr != '\0'; ptr++) {
|
||||
int digit = DigitValue(*ptr);
|
||||
if (digit < 0 || digit >= base) {
|
||||
@@ -886,7 +937,8 @@ bool Tokenizer::ParseInteger(const string& text, uint64 max_value,
|
||||
// token, but Tokenizer still think it's integer.
|
||||
return false;
|
||||
}
|
||||
if (digit > max_value || result > (max_value - digit) / base) {
|
||||
if (static_cast<uint64_t>(digit) > max_value ||
|
||||
result > (max_value - digit) / base) {
|
||||
// Overflow.
|
||||
return false;
|
||||
}
|
||||
@@ -897,7 +949,7 @@ bool Tokenizer::ParseInteger(const string& text, uint64 max_value,
|
||||
return true;
|
||||
}
|
||||
|
||||
double Tokenizer::ParseFloat(const string& text) {
|
||||
double Tokenizer::ParseFloat(const std::string& text) {
|
||||
const char* start = text.c_str();
|
||||
char* end;
|
||||
double result = NoLocaleStrtod(start, &end);
|
||||
@@ -916,41 +968,38 @@ double Tokenizer::ParseFloat(const string& text) {
|
||||
++end;
|
||||
}
|
||||
|
||||
GOOGLE_LOG_IF(DFATAL, end - start != text.size() || *start == '-')
|
||||
<< " Tokenizer::ParseFloat() passed text that could not have been"
|
||||
" tokenized as a float: " << CEscape(text);
|
||||
GOOGLE_LOG_IF(DFATAL,
|
||||
static_cast<size_t>(end - start) != text.size() || *start == '-')
|
||||
<< " Tokenizer::ParseFloat() passed text that could not have been"
|
||||
" tokenized as a float: "
|
||||
<< CEscape(text);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Helper to append a Unicode code point to a string as UTF8, without bringing
|
||||
// in any external dependencies.
|
||||
static void AppendUTF8(uint32 code_point, string* output) {
|
||||
uint32 tmp = 0;
|
||||
static void AppendUTF8(uint32_t code_point, std::string* output) {
|
||||
uint32_t tmp = 0;
|
||||
int len = 0;
|
||||
if (code_point <= 0x7f) {
|
||||
tmp = code_point;
|
||||
len = 1;
|
||||
} else if (code_point <= 0x07ff) {
|
||||
tmp = 0x0000c080 |
|
||||
((code_point & 0x07c0) << 2) |
|
||||
(code_point & 0x003f);
|
||||
tmp = 0x0000c080 | ((code_point & 0x07c0) << 2) | (code_point & 0x003f);
|
||||
len = 2;
|
||||
} else if (code_point <= 0xffff) {
|
||||
tmp = 0x00e08080 |
|
||||
((code_point & 0xf000) << 4) |
|
||||
((code_point & 0x0fc0) << 2) |
|
||||
(code_point & 0x003f);
|
||||
tmp = 0x00e08080 | ((code_point & 0xf000) << 4) |
|
||||
((code_point & 0x0fc0) << 2) | (code_point & 0x003f);
|
||||
len = 3;
|
||||
} else if (code_point <= 0x1fffff) {
|
||||
tmp = 0xf0808080 |
|
||||
((code_point & 0x1c0000) << 6) |
|
||||
((code_point & 0x03f000) << 4) |
|
||||
((code_point & 0x000fc0) << 2) |
|
||||
(code_point & 0x003f);
|
||||
} else if (code_point <= 0x10ffff) {
|
||||
tmp = 0xf0808080 | ((code_point & 0x1c0000) << 6) |
|
||||
((code_point & 0x03f000) << 4) | ((code_point & 0x000fc0) << 2) |
|
||||
(code_point & 0x003f);
|
||||
len = 4;
|
||||
} else {
|
||||
// UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is
|
||||
// normally only defined up to there as well.
|
||||
// Unicode code points end at 0x10FFFF, so this is out-of-range.
|
||||
// ConsumeString permits hex values up to 0x1FFFFF, and FetchUnicodePoint
|
||||
// doesn't perform a range check.
|
||||
StringAppendF(output, "\\U%08x", code_point);
|
||||
return;
|
||||
}
|
||||
@@ -960,7 +1009,7 @@ static void AppendUTF8(uint32 code_point, string* output) {
|
||||
|
||||
// Try to read <len> hex digits from ptr, and stuff the numeric result into
|
||||
// *result. Returns true if that many digits were successfully consumed.
|
||||
static bool ReadHexDigits(const char* ptr, int len, uint32* result) {
|
||||
static bool ReadHexDigits(const char* ptr, int len, uint32_t* result) {
|
||||
*result = 0;
|
||||
if (len == 0) return false;
|
||||
for (const char* end = ptr + len; ptr < end; ++ptr) {
|
||||
@@ -975,26 +1024,27 @@ static bool ReadHexDigits(const char* ptr, int len, uint32* result) {
|
||||
// surrogate. These numbers are in a reserved range of Unicode code points, so
|
||||
// if we encounter such a pair we know how to parse it and convert it into a
|
||||
// single code point.
|
||||
static const uint32 kMinHeadSurrogate = 0xd800;
|
||||
static const uint32 kMaxHeadSurrogate = 0xdc00;
|
||||
static const uint32 kMinTrailSurrogate = 0xdc00;
|
||||
static const uint32 kMaxTrailSurrogate = 0xe000;
|
||||
static const uint32_t kMinHeadSurrogate = 0xd800;
|
||||
static const uint32_t kMaxHeadSurrogate = 0xdc00;
|
||||
static const uint32_t kMinTrailSurrogate = 0xdc00;
|
||||
static const uint32_t kMaxTrailSurrogate = 0xe000;
|
||||
|
||||
static inline bool IsHeadSurrogate(uint32 code_point) {
|
||||
static inline bool IsHeadSurrogate(uint32_t code_point) {
|
||||
return (code_point >= kMinHeadSurrogate) && (code_point < kMaxHeadSurrogate);
|
||||
}
|
||||
|
||||
static inline bool IsTrailSurrogate(uint32 code_point) {
|
||||
static inline bool IsTrailSurrogate(uint32_t code_point) {
|
||||
return (code_point >= kMinTrailSurrogate) &&
|
||||
(code_point < kMaxTrailSurrogate);
|
||||
(code_point < kMaxTrailSurrogate);
|
||||
}
|
||||
|
||||
// Combine a head and trail surrogate into a single Unicode code point.
|
||||
static uint32 AssembleUTF16(uint32 head_surrogate, uint32 trail_surrogate) {
|
||||
static uint32_t AssembleUTF16(uint32_t head_surrogate,
|
||||
uint32_t trail_surrogate) {
|
||||
GOOGLE_DCHECK(IsHeadSurrogate(head_surrogate));
|
||||
GOOGLE_DCHECK(IsTrailSurrogate(trail_surrogate));
|
||||
return 0x10000 + (((head_surrogate - kMinHeadSurrogate) << 10) |
|
||||
(trail_surrogate - kMinTrailSurrogate));
|
||||
(trail_surrogate - kMinTrailSurrogate));
|
||||
}
|
||||
|
||||
// Convert the escape sequence parameter to a number of expected hex digits.
|
||||
@@ -1008,12 +1058,11 @@ static inline int UnicodeLength(char key) {
|
||||
// to parse that sequence. On success, returns a pointer to the first char
|
||||
// beyond that sequence, and fills in *code_point. On failure, returns ptr
|
||||
// itself.
|
||||
static const char* FetchUnicodePoint(const char* ptr, uint32* code_point) {
|
||||
static const char* FetchUnicodePoint(const char* ptr, uint32_t* code_point) {
|
||||
const char* p = ptr;
|
||||
// Fetch the code point.
|
||||
const int len = UnicodeLength(*p++);
|
||||
if (!ReadHexDigits(p, len, code_point))
|
||||
return ptr;
|
||||
if (!ReadHexDigits(p, len, code_point)) return ptr;
|
||||
p += len;
|
||||
|
||||
// Check if the code point we read is a "head surrogate." If so, then we
|
||||
@@ -1021,7 +1070,7 @@ static const char* FetchUnicodePoint(const char* ptr, uint32* code_point) {
|
||||
// "trail surrogate," and together they form a UTF-16 pair which decodes into
|
||||
// a single Unicode point. Trail surrogates may only use \u, not \U.
|
||||
if (IsHeadSurrogate(*code_point) && *p == '\\' && *(p + 1) == 'u') {
|
||||
uint32 trail_surrogate;
|
||||
uint32_t trail_surrogate;
|
||||
if (ReadHexDigits(p + 2, 4, &trail_surrogate) &&
|
||||
IsTrailSurrogate(trail_surrogate)) {
|
||||
*code_point = AssembleUTF16(*code_point, trail_surrogate);
|
||||
@@ -1036,14 +1085,15 @@ static const char* FetchUnicodePoint(const char* ptr, uint32* code_point) {
|
||||
|
||||
// The text string must begin and end with single or double quote
|
||||
// characters.
|
||||
void Tokenizer::ParseStringAppend(const string& text, string* output) {
|
||||
void Tokenizer::ParseStringAppend(const std::string& text,
|
||||
std::string* output) {
|
||||
// Reminder: text[0] is always a quote character. (If text is
|
||||
// empty, it's invalid, so we'll just return).
|
||||
const size_t text_size = text.size();
|
||||
if (text_size == 0) {
|
||||
GOOGLE_LOG(DFATAL)
|
||||
<< " Tokenizer::ParseStringAppend() passed text that could not"
|
||||
" have been tokenized as a string: " << CEscape(text);
|
||||
GOOGLE_LOG(DFATAL) << " Tokenizer::ParseStringAppend() passed text that could not"
|
||||
" have been tokenized as a string: "
|
||||
<< CEscape(text);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1092,7 +1142,7 @@ void Tokenizer::ParseStringAppend(const string& text, string* output) {
|
||||
output->push_back(static_cast<char>(code));
|
||||
|
||||
} else if (*ptr == 'u' || *ptr == 'U') {
|
||||
uint32 unicode;
|
||||
uint32_t unicode;
|
||||
const char* end = FetchUnicodePoint(ptr, &unicode);
|
||||
if (end == ptr) {
|
||||
// Failure: Just dump out what we saw, don't try to parse it.
|
||||
@@ -1114,23 +1164,19 @@ void Tokenizer::ParseStringAppend(const string& text, string* output) {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename CharacterClass>
|
||||
static bool AllInClass(const string& s) {
|
||||
for (int i = 0; i < s.size(); ++i) {
|
||||
if (!CharacterClass::InClass(s[i]))
|
||||
return false;
|
||||
template <typename CharacterClass>
|
||||
static bool AllInClass(const std::string& s) {
|
||||
for (const char character : s) {
|
||||
if (!CharacterClass::InClass(character)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tokenizer::IsIdentifier(const string& text) {
|
||||
bool Tokenizer::IsIdentifier(const std::string& text) {
|
||||
// Mirrors IDENTIFIER definition in Tokenizer::Next() above.
|
||||
if (text.size() == 0)
|
||||
return false;
|
||||
if (!Letter::InClass(text.at(0)))
|
||||
return false;
|
||||
if (!AllInClass<Alphanumeric>(text.substr(1)))
|
||||
return false;
|
||||
if (text.size() == 0) return false;
|
||||
if (!Letter::InClass(text.at(0))) return false;
|
||||
if (!AllInClass<Alphanumeric>(text.substr(1))) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+71
-42
@@ -37,16 +37,19 @@
|
||||
#ifndef GOOGLE_PROTOBUF_IO_TOKENIZER_H__
|
||||
#define GOOGLE_PROTOBUF_IO_TOKENIZER_H__
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
class ZeroCopyInputStream; // zero_copy_stream.h
|
||||
class ZeroCopyInputStream; // zero_copy_stream.h
|
||||
|
||||
// Defined in this file.
|
||||
class ErrorCollector;
|
||||
@@ -61,7 +64,7 @@ typedef int ColumnNumber;
|
||||
// Abstract interface for an object which collects the errors that occur
|
||||
// during parsing. A typical implementation might simply print the errors
|
||||
// to stdout.
|
||||
class LIBPROTOBUF_EXPORT ErrorCollector {
|
||||
class PROTOBUF_EXPORT ErrorCollector {
|
||||
public:
|
||||
inline ErrorCollector() {}
|
||||
virtual ~ErrorCollector();
|
||||
@@ -70,13 +73,13 @@ class LIBPROTOBUF_EXPORT ErrorCollector {
|
||||
// column numbers. The numbers are zero-based, so you may want to add
|
||||
// 1 to each before printing them.
|
||||
virtual void AddError(int line, ColumnNumber column,
|
||||
const string& message) = 0;
|
||||
const std::string& message) = 0;
|
||||
|
||||
// Indicates that there was a warning in the input at the given line and
|
||||
// column numbers. The numbers are zero-based, so you may want to add
|
||||
// 1 to each before printing them.
|
||||
virtual void AddWarning(int line, ColumnNumber column,
|
||||
const string& message) { }
|
||||
virtual void AddWarning(int /* line */, ColumnNumber /* column */,
|
||||
const std::string& /* message */) {}
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector);
|
||||
@@ -88,7 +91,7 @@ class LIBPROTOBUF_EXPORT ErrorCollector {
|
||||
// precise descriptions. Whitespace and comments are skipped. By default,
|
||||
// C- and C++-style comments are recognized, but other styles can be used by
|
||||
// calling set_comment_style().
|
||||
class LIBPROTOBUF_EXPORT Tokenizer {
|
||||
class PROTOBUF_EXPORT Tokenizer {
|
||||
public:
|
||||
// Construct a Tokenizer that reads and tokenizes text from the given
|
||||
// input stream and writes errors to the given error_collector.
|
||||
@@ -97,8 +100,8 @@ class LIBPROTOBUF_EXPORT Tokenizer {
|
||||
~Tokenizer();
|
||||
|
||||
enum TokenType {
|
||||
TYPE_START, // Next() has not yet been called.
|
||||
TYPE_END, // End of input reached. "text" is empty.
|
||||
TYPE_START, // Next() has not yet been called.
|
||||
TYPE_END, // End of input reached. "text" is empty.
|
||||
|
||||
TYPE_IDENTIFIER, // A sequence of letters, digits, and underscores, not
|
||||
// starting with a digit. It is an error for a number
|
||||
@@ -119,12 +122,19 @@ class LIBPROTOBUF_EXPORT Tokenizer {
|
||||
TYPE_SYMBOL, // Any other printable character, like '!' or '+'.
|
||||
// Symbols are always a single character, so "!+$%" is
|
||||
// four tokens.
|
||||
TYPE_WHITESPACE, // A sequence of whitespace. This token type is only
|
||||
// produced if report_whitespace() is true. It is not
|
||||
// reported for whitespace within comments or strings.
|
||||
TYPE_NEWLINE, // A newline (\n). This token type is only
|
||||
// produced if report_whitespace() is true and
|
||||
// report_newlines() is true. It is not reported for
|
||||
// newlines in comments or strings.
|
||||
};
|
||||
|
||||
// Structure representing a token read from the token stream.
|
||||
struct Token {
|
||||
TokenType type;
|
||||
string text; // The exact text of the token as it appeared in
|
||||
std::string text; // The exact text of the token as it appeared in
|
||||
// the input. e.g. tokens of TYPE_STRING will still
|
||||
// be escaped and in quotes.
|
||||
|
||||
@@ -190,32 +200,32 @@ class LIBPROTOBUF_EXPORT Tokenizer {
|
||||
// /* Block comment attached to
|
||||
// * grault. */
|
||||
// optional int32 grault = 6;
|
||||
bool NextWithComments(string* prev_trailing_comments,
|
||||
std::vector<string>* detached_comments,
|
||||
string* next_leading_comments);
|
||||
bool NextWithComments(std::string* prev_trailing_comments,
|
||||
std::vector<std::string>* detached_comments,
|
||||
std::string* next_leading_comments);
|
||||
|
||||
// Parse helpers ---------------------------------------------------
|
||||
|
||||
// Parses a TYPE_FLOAT token. This never fails, so long as the text actually
|
||||
// comes from a TYPE_FLOAT token parsed by Tokenizer. If it doesn't, the
|
||||
// result is undefined (possibly an assert failure).
|
||||
static double ParseFloat(const string& text);
|
||||
static double ParseFloat(const std::string& text);
|
||||
|
||||
// Parses a TYPE_STRING token. This never fails, so long as the text actually
|
||||
// comes from a TYPE_STRING token parsed by Tokenizer. If it doesn't, the
|
||||
// result is undefined (possibly an assert failure).
|
||||
static void ParseString(const string& text, string* output);
|
||||
static void ParseString(const std::string& text, std::string* output);
|
||||
|
||||
// Identical to ParseString, but appends to output.
|
||||
static void ParseStringAppend(const string& text, string* output);
|
||||
static void ParseStringAppend(const std::string& text, std::string* output);
|
||||
|
||||
// Parses a TYPE_INTEGER token. Returns false if the result would be
|
||||
// greater than max_value. Otherwise, returns true and sets *output to the
|
||||
// result. If the text is not from a Token of type TYPE_INTEGER originally
|
||||
// parsed by a Tokenizer, the result is undefined (possibly an assert
|
||||
// failure).
|
||||
static bool ParseInteger(const string& text, uint64 max_value,
|
||||
uint64* output);
|
||||
static bool ParseInteger(const std::string& text, uint64_t max_value,
|
||||
uint64_t* output);
|
||||
|
||||
// Options ---------------------------------------------------------
|
||||
|
||||
@@ -249,24 +259,34 @@ class LIBPROTOBUF_EXPORT Tokenizer {
|
||||
allow_multiline_strings_ = allow;
|
||||
}
|
||||
|
||||
// If true, whitespace tokens are reported by Next().
|
||||
// Note: `set_report_whitespace(false)` implies `set_report_newlines(false)`.
|
||||
bool report_whitespace() const;
|
||||
void set_report_whitespace(bool report);
|
||||
|
||||
// If true, newline tokens are reported by Next().
|
||||
// Note: `set_report_newlines(true)` implies `set_report_whitespace(true)`.
|
||||
bool report_newlines() const;
|
||||
void set_report_newlines(bool report);
|
||||
|
||||
// External helper: validate an identifier.
|
||||
static bool IsIdentifier(const string& text);
|
||||
static bool IsIdentifier(const std::string& text);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer);
|
||||
|
||||
Token current_; // Returned by current().
|
||||
Token previous_; // Returned by previous().
|
||||
Token current_; // Returned by current().
|
||||
Token previous_; // Returned by previous().
|
||||
|
||||
ZeroCopyInputStream* input_;
|
||||
ErrorCollector* error_collector_;
|
||||
|
||||
char current_char_; // == buffer_[buffer_pos_], updated by NextChar().
|
||||
const char* buffer_; // Current buffer returned from input_.
|
||||
int buffer_size_; // Size of buffer_.
|
||||
int buffer_pos_; // Current position within the buffer.
|
||||
bool read_error_; // Did we previously encounter a read error?
|
||||
char current_char_; // == buffer_[buffer_pos_], updated by NextChar().
|
||||
const char* buffer_; // Current buffer returned from input_.
|
||||
int buffer_size_; // Size of buffer_.
|
||||
int buffer_pos_; // Current position within the buffer.
|
||||
bool read_error_; // Did we previously encounter a read error?
|
||||
|
||||
// Line and column number of current_char_ within the whole input stream.
|
||||
int line_;
|
||||
@@ -276,7 +296,7 @@ class LIBPROTOBUF_EXPORT Tokenizer {
|
||||
// Call RecordTo(&str) to start recording and StopRecording() to stop.
|
||||
// E.g. StartToken() calls RecordTo(¤t_.text). record_start_ is the
|
||||
// position within the current buffer where recording started.
|
||||
string* record_target_;
|
||||
std::string* record_target_;
|
||||
int record_start_;
|
||||
|
||||
// Options.
|
||||
@@ -284,6 +304,8 @@ class LIBPROTOBUF_EXPORT Tokenizer {
|
||||
CommentStyle comment_style_;
|
||||
bool require_space_after_number_;
|
||||
bool allow_multiline_strings_;
|
||||
bool report_whitespace_ = false;
|
||||
bool report_newlines_ = false;
|
||||
|
||||
// Since we count columns we need to interpret tabs somehow. We'll take
|
||||
// the standard 8-character definition for lack of any way to do better.
|
||||
@@ -299,7 +321,7 @@ class LIBPROTOBUF_EXPORT Tokenizer {
|
||||
// Read a new buffer from the input.
|
||||
void Refresh();
|
||||
|
||||
inline void RecordTo(string* target);
|
||||
inline void RecordTo(std::string* target);
|
||||
inline void StopRecording();
|
||||
|
||||
// Called when the current character is the first character of a new
|
||||
@@ -311,7 +333,7 @@ class LIBPROTOBUF_EXPORT Tokenizer {
|
||||
inline void EndToken();
|
||||
|
||||
// Convenience method to add an error at the current line and column.
|
||||
void AddError(const string& message) {
|
||||
void AddError(const std::string& message) {
|
||||
error_collector_->AddError(line_, column_, message);
|
||||
}
|
||||
|
||||
@@ -334,9 +356,9 @@ class LIBPROTOBUF_EXPORT Tokenizer {
|
||||
TokenType ConsumeNumber(bool started_with_zero, bool started_with_dot);
|
||||
|
||||
// Consume the rest of a line.
|
||||
void ConsumeLineComment(string* content);
|
||||
void ConsumeLineComment(std::string* content);
|
||||
// Consume until "*/".
|
||||
void ConsumeBlockComment(string* content);
|
||||
void ConsumeBlockComment(std::string* content);
|
||||
|
||||
enum NextCommentStatus {
|
||||
// Started a line comment.
|
||||
@@ -357,6 +379,14 @@ class LIBPROTOBUF_EXPORT Tokenizer {
|
||||
// of comment it is.
|
||||
NextCommentStatus TryConsumeCommentStart();
|
||||
|
||||
// If we're looking at a TYPE_WHITESPACE token and `report_whitespace_` is
|
||||
// true, consume it and return true.
|
||||
bool TryConsumeWhitespace();
|
||||
|
||||
// If we're looking at a TYPE_NEWLINE token and `report_newlines_` is true,
|
||||
// consume it and return true.
|
||||
bool TryConsumeNewline();
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// These helper methods make the parsing code more readable. The
|
||||
// "character classes" referred to are defined at the top of the .cc file.
|
||||
@@ -367,45 +397,44 @@ class LIBPROTOBUF_EXPORT Tokenizer {
|
||||
|
||||
// Returns true if the current character is of the given character
|
||||
// class, but does not consume anything.
|
||||
template<typename CharacterClass>
|
||||
template <typename CharacterClass>
|
||||
inline bool LookingAt();
|
||||
|
||||
// If the current character is in the given class, consume it and return
|
||||
// true. Otherwise return false.
|
||||
// e.g. TryConsumeOne<Letter>()
|
||||
template<typename CharacterClass>
|
||||
template <typename CharacterClass>
|
||||
inline bool TryConsumeOne();
|
||||
|
||||
// Like above, but try to consume the specific character indicated.
|
||||
inline bool TryConsume(char c);
|
||||
|
||||
// Consume zero or more of the given character class.
|
||||
template<typename CharacterClass>
|
||||
template <typename CharacterClass>
|
||||
inline void ConsumeZeroOrMore();
|
||||
|
||||
// Consume one or more of the given character class or log the given
|
||||
// error message.
|
||||
// e.g. ConsumeOneOrMore<Digit>("Expected digits.");
|
||||
template<typename CharacterClass>
|
||||
template <typename CharacterClass>
|
||||
inline void ConsumeOneOrMore(const char* error);
|
||||
};
|
||||
|
||||
// inline methods ====================================================
|
||||
inline const Tokenizer::Token& Tokenizer::current() {
|
||||
return current_;
|
||||
}
|
||||
inline const Tokenizer::Token& Tokenizer::current() { return current_; }
|
||||
|
||||
inline const Tokenizer::Token& Tokenizer::previous() {
|
||||
return previous_;
|
||||
}
|
||||
inline const Tokenizer::Token& Tokenizer::previous() { return previous_; }
|
||||
|
||||
inline void Tokenizer::ParseString(const string& text, string* output) {
|
||||
inline void Tokenizer::ParseString(const std::string& text,
|
||||
std::string* output) {
|
||||
output->clear();
|
||||
ParseStringAppend(text, output);
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_TOKENIZER_H__
|
||||
|
||||
+11
-6
@@ -107,11 +107,14 @@
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
@@ -121,7 +124,7 @@ class ZeroCopyOutputStream;
|
||||
|
||||
// Abstract interface similar to an input stream but designed to minimize
|
||||
// copying.
|
||||
class LIBPROTOBUF_EXPORT ZeroCopyInputStream {
|
||||
class PROTOBUF_EXPORT ZeroCopyInputStream {
|
||||
public:
|
||||
ZeroCopyInputStream() {}
|
||||
virtual ~ZeroCopyInputStream() {}
|
||||
@@ -169,7 +172,7 @@ class LIBPROTOBUF_EXPORT ZeroCopyInputStream {
|
||||
virtual bool Skip(int count) = 0;
|
||||
|
||||
// Returns the total number of bytes read since this object was created.
|
||||
virtual int64 ByteCount() const = 0;
|
||||
virtual int64_t ByteCount() const = 0;
|
||||
|
||||
|
||||
private:
|
||||
@@ -178,7 +181,7 @@ class LIBPROTOBUF_EXPORT ZeroCopyInputStream {
|
||||
|
||||
// Abstract interface similar to an output stream but designed to minimize
|
||||
// copying.
|
||||
class LIBPROTOBUF_EXPORT ZeroCopyOutputStream {
|
||||
class PROTOBUF_EXPORT ZeroCopyOutputStream {
|
||||
public:
|
||||
ZeroCopyOutputStream() {}
|
||||
virtual ~ZeroCopyOutputStream() {}
|
||||
@@ -224,7 +227,7 @@ class LIBPROTOBUF_EXPORT ZeroCopyOutputStream {
|
||||
virtual void BackUp(int count) = 0;
|
||||
|
||||
// Returns the total number of bytes written since this object was created.
|
||||
virtual int64 ByteCount() const = 0;
|
||||
virtual int64_t ByteCount() const = 0;
|
||||
|
||||
// Write a given chunk of data to the output. Some output streams may
|
||||
// implement this in a way that avoids copying. Check AllowsAliasing() before
|
||||
@@ -243,6 +246,8 @@ class LIBPROTOBUF_EXPORT ZeroCopyOutputStream {
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
||||
|
||||
+56
-150
@@ -33,19 +33,21 @@
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <algorithm>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/io/io_win32.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
#include <google/protobuf/stubs/io_win32.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
@@ -58,11 +60,11 @@ namespace io {
|
||||
#define lseek(fd, offset, origin) ((off_t)-1)
|
||||
// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
|
||||
// them like we do below.
|
||||
using google::protobuf::internal::win32::access;
|
||||
using google::protobuf::internal::win32::close;
|
||||
using google::protobuf::internal::win32::open;
|
||||
using google::protobuf::internal::win32::read;
|
||||
using google::protobuf::internal::win32::write;
|
||||
using google::protobuf::io::win32::access;
|
||||
using google::protobuf::io::win32::close;
|
||||
using google::protobuf::io::win32::open;
|
||||
using google::protobuf::io::win32::read;
|
||||
using google::protobuf::io::win32::write;
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
@@ -78,41 +80,35 @@ int close_no_eintr(int fd) {
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
FileInputStream::FileInputStream(int file_descriptor, int block_size)
|
||||
: copying_input_(file_descriptor),
|
||||
impl_(©ing_input_, block_size) {
|
||||
}
|
||||
: copying_input_(file_descriptor), impl_(©ing_input_, block_size) {}
|
||||
|
||||
bool FileInputStream::Close() {
|
||||
return copying_input_.Close();
|
||||
}
|
||||
bool FileInputStream::Close() { return copying_input_.Close(); }
|
||||
|
||||
bool FileInputStream::Next(const void** data, int* size) {
|
||||
return impl_.Next(data, size);
|
||||
}
|
||||
|
||||
void FileInputStream::BackUp(int count) {
|
||||
impl_.BackUp(count);
|
||||
}
|
||||
void FileInputStream::BackUp(int count) { impl_.BackUp(count); }
|
||||
|
||||
bool FileInputStream::Skip(int count) {
|
||||
return impl_.Skip(count);
|
||||
}
|
||||
bool FileInputStream::Skip(int count) { return impl_.Skip(count); }
|
||||
|
||||
int64 FileInputStream::ByteCount() const {
|
||||
return impl_.ByteCount();
|
||||
}
|
||||
int64_t FileInputStream::ByteCount() const { return impl_.ByteCount(); }
|
||||
|
||||
FileInputStream::CopyingFileInputStream::CopyingFileInputStream(
|
||||
int file_descriptor)
|
||||
: file_(file_descriptor),
|
||||
close_on_delete_(false),
|
||||
is_closed_(false),
|
||||
errno_(0),
|
||||
previous_seek_failed_(false) {
|
||||
: file_(file_descriptor),
|
||||
close_on_delete_(false),
|
||||
is_closed_(false),
|
||||
errno_(0),
|
||||
previous_seek_failed_(false) {
|
||||
#ifndef _WIN32
|
||||
int flags = fcntl(file_, F_GETFL);
|
||||
flags &= ~O_NONBLOCK;
|
||||
fcntl(file_, F_SETFL, flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
FileInputStream::CopyingFileInputStream::~CopyingFileInputStream() {
|
||||
@@ -157,8 +153,7 @@ int FileInputStream::CopyingFileInputStream::Read(void* buffer, int size) {
|
||||
int FileInputStream::CopyingFileInputStream::Skip(int count) {
|
||||
GOOGLE_CHECK(!is_closed_);
|
||||
|
||||
if (!previous_seek_failed_ &&
|
||||
lseek(file_, count, SEEK_CUR) != (off_t)-1) {
|
||||
if (!previous_seek_failed_ && lseek(file_, count, SEEK_CUR) != (off_t)-1) {
|
||||
// Seek succeeded.
|
||||
return count;
|
||||
} else {
|
||||
@@ -175,43 +170,23 @@ int FileInputStream::CopyingFileInputStream::Skip(int count) {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
FileOutputStream::FileOutputStream(int file_descriptor, int block_size)
|
||||
: copying_output_(file_descriptor),
|
||||
impl_(©ing_output_, block_size) {
|
||||
}
|
||||
|
||||
FileOutputStream::~FileOutputStream() {
|
||||
impl_.Flush();
|
||||
}
|
||||
FileOutputStream::FileOutputStream(int file_descriptor, int /*block_size*/)
|
||||
: CopyingOutputStreamAdaptor(©ing_output_),
|
||||
copying_output_(file_descriptor) {}
|
||||
|
||||
bool FileOutputStream::Close() {
|
||||
bool flush_succeeded = impl_.Flush();
|
||||
bool flush_succeeded = Flush();
|
||||
return copying_output_.Close() && flush_succeeded;
|
||||
}
|
||||
|
||||
bool FileOutputStream::Flush() {
|
||||
return impl_.Flush();
|
||||
}
|
||||
|
||||
bool FileOutputStream::Next(void** data, int* size) {
|
||||
return impl_.Next(data, size);
|
||||
}
|
||||
|
||||
void FileOutputStream::BackUp(int count) {
|
||||
impl_.BackUp(count);
|
||||
}
|
||||
|
||||
int64 FileOutputStream::ByteCount() const {
|
||||
return impl_.ByteCount();
|
||||
}
|
||||
|
||||
FileOutputStream::CopyingFileOutputStream::CopyingFileOutputStream(
|
||||
int file_descriptor)
|
||||
: file_(file_descriptor),
|
||||
close_on_delete_(false),
|
||||
is_closed_(false),
|
||||
errno_(0) {
|
||||
}
|
||||
: file_(file_descriptor),
|
||||
close_on_delete_(false),
|
||||
is_closed_(false),
|
||||
errno_(0) {}
|
||||
|
||||
FileOutputStream::~FileOutputStream() { Flush(); }
|
||||
|
||||
FileOutputStream::CopyingFileOutputStream::~CopyingFileOutputStream() {
|
||||
if (close_on_delete_) {
|
||||
@@ -236,12 +211,12 @@ bool FileOutputStream::CopyingFileOutputStream::Close() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileOutputStream::CopyingFileOutputStream::Write(
|
||||
const void* buffer, int size) {
|
||||
bool FileOutputStream::CopyingFileOutputStream::Write(const void* buffer,
|
||||
int size) {
|
||||
GOOGLE_CHECK(!is_closed_);
|
||||
int total_written = 0;
|
||||
|
||||
const uint8* buffer_base = reinterpret_cast<const uint8*>(buffer);
|
||||
const uint8_t* buffer_base = reinterpret_cast<const uint8_t*>(buffer);
|
||||
|
||||
while (total_written < size) {
|
||||
int bytes;
|
||||
@@ -280,17 +255,11 @@ bool IstreamInputStream::Next(const void** data, int* size) {
|
||||
return impl_.Next(data, size);
|
||||
}
|
||||
|
||||
void IstreamInputStream::BackUp(int count) {
|
||||
impl_.BackUp(count);
|
||||
}
|
||||
void IstreamInputStream::BackUp(int count) { impl_.BackUp(count); }
|
||||
|
||||
bool IstreamInputStream::Skip(int count) {
|
||||
return impl_.Skip(count);
|
||||
}
|
||||
bool IstreamInputStream::Skip(int count) { return impl_.Skip(count); }
|
||||
|
||||
int64 IstreamInputStream::ByteCount() const {
|
||||
return impl_.ByteCount();
|
||||
}
|
||||
int64_t IstreamInputStream::ByteCount() const { return impl_.ByteCount(); }
|
||||
|
||||
IstreamInputStream::CopyingIstreamInputStream::CopyingIstreamInputStream(
|
||||
std::istream* input)
|
||||
@@ -298,8 +267,8 @@ IstreamInputStream::CopyingIstreamInputStream::CopyingIstreamInputStream(
|
||||
|
||||
IstreamInputStream::CopyingIstreamInputStream::~CopyingIstreamInputStream() {}
|
||||
|
||||
int IstreamInputStream::CopyingIstreamInputStream::Read(
|
||||
void* buffer, int size) {
|
||||
int IstreamInputStream::CopyingIstreamInputStream::Read(void* buffer,
|
||||
int size) {
|
||||
input_->read(reinterpret_cast<char*>(buffer), size);
|
||||
int result = input_->gcount();
|
||||
if (result == 0 && input_->fail() && !input_->eof()) {
|
||||
@@ -313,21 +282,15 @@ int IstreamInputStream::CopyingIstreamInputStream::Read(
|
||||
OstreamOutputStream::OstreamOutputStream(std::ostream* output, int block_size)
|
||||
: copying_output_(output), impl_(©ing_output_, block_size) {}
|
||||
|
||||
OstreamOutputStream::~OstreamOutputStream() {
|
||||
impl_.Flush();
|
||||
}
|
||||
OstreamOutputStream::~OstreamOutputStream() { impl_.Flush(); }
|
||||
|
||||
bool OstreamOutputStream::Next(void** data, int* size) {
|
||||
return impl_.Next(data, size);
|
||||
}
|
||||
|
||||
void OstreamOutputStream::BackUp(int count) {
|
||||
impl_.BackUp(count);
|
||||
}
|
||||
void OstreamOutputStream::BackUp(int count) { impl_.BackUp(count); }
|
||||
|
||||
int64 OstreamOutputStream::ByteCount() const {
|
||||
return impl_.ByteCount();
|
||||
}
|
||||
int64_t OstreamOutputStream::ByteCount() const { return impl_.ByteCount(); }
|
||||
|
||||
OstreamOutputStream::CopyingOstreamOutputStream::CopyingOstreamOutputStream(
|
||||
std::ostream* output)
|
||||
@@ -336,8 +299,8 @@ OstreamOutputStream::CopyingOstreamOutputStream::CopyingOstreamOutputStream(
|
||||
OstreamOutputStream::CopyingOstreamOutputStream::~CopyingOstreamOutputStream() {
|
||||
}
|
||||
|
||||
bool OstreamOutputStream::CopyingOstreamOutputStream::Write(
|
||||
const void* buffer, int size) {
|
||||
bool OstreamOutputStream::CopyingOstreamOutputStream::Write(const void* buffer,
|
||||
int size) {
|
||||
output_->write(reinterpret_cast<const char*>(buffer), size);
|
||||
return output_->good();
|
||||
}
|
||||
@@ -346,7 +309,7 @@ bool OstreamOutputStream::CopyingOstreamOutputStream::Write(
|
||||
|
||||
ConcatenatingInputStream::ConcatenatingInputStream(
|
||||
ZeroCopyInputStream* const streams[], int count)
|
||||
: streams_(streams), stream_count_(count), bytes_retired_(0) {
|
||||
: streams_(streams), stream_count_(count), bytes_retired_(0) {
|
||||
}
|
||||
|
||||
bool ConcatenatingInputStream::Next(const void** data, int* size) {
|
||||
@@ -375,12 +338,12 @@ bool ConcatenatingInputStream::Skip(int count) {
|
||||
while (stream_count_ > 0) {
|
||||
// Assume that ByteCount() can be used to find out how much we actually
|
||||
// skipped when Skip() fails.
|
||||
int64 target_byte_count = streams_[0]->ByteCount() + count;
|
||||
int64_t target_byte_count = streams_[0]->ByteCount() + count;
|
||||
if (streams_[0]->Skip(count)) return true;
|
||||
|
||||
// Hit the end of the stream. Figure out how many more bytes we still have
|
||||
// to skip.
|
||||
int64 final_byte_count = streams_[0]->ByteCount();
|
||||
int64_t final_byte_count = streams_[0]->ByteCount();
|
||||
GOOGLE_DCHECK_LT(final_byte_count, target_byte_count);
|
||||
count = target_byte_count - final_byte_count;
|
||||
|
||||
@@ -393,7 +356,7 @@ bool ConcatenatingInputStream::Skip(int count) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int64 ConcatenatingInputStream::ByteCount() const {
|
||||
int64_t ConcatenatingInputStream::ByteCount() const {
|
||||
if (stream_count_ == 0) {
|
||||
return bytes_retired_;
|
||||
} else {
|
||||
@@ -402,63 +365,6 @@ int64 ConcatenatingInputStream::ByteCount() const {
|
||||
}
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
LimitingInputStream::LimitingInputStream(ZeroCopyInputStream* input,
|
||||
int64 limit)
|
||||
: input_(input), limit_(limit) {
|
||||
prior_bytes_read_ = input_->ByteCount();
|
||||
}
|
||||
|
||||
LimitingInputStream::~LimitingInputStream() {
|
||||
// If we overshot the limit, back up.
|
||||
if (limit_ < 0) input_->BackUp(-limit_);
|
||||
}
|
||||
|
||||
bool LimitingInputStream::Next(const void** data, int* size) {
|
||||
if (limit_ <= 0) return false;
|
||||
if (!input_->Next(data, size)) return false;
|
||||
|
||||
limit_ -= *size;
|
||||
if (limit_ < 0) {
|
||||
// We overshot the limit. Reduce *size to hide the rest of the buffer.
|
||||
*size += limit_;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LimitingInputStream::BackUp(int count) {
|
||||
if (limit_ < 0) {
|
||||
input_->BackUp(count - limit_);
|
||||
limit_ = count;
|
||||
} else {
|
||||
input_->BackUp(count);
|
||||
limit_ += count;
|
||||
}
|
||||
}
|
||||
|
||||
bool LimitingInputStream::Skip(int count) {
|
||||
if (count > limit_) {
|
||||
if (limit_ < 0) return false;
|
||||
input_->Skip(limit_);
|
||||
limit_ = 0;
|
||||
return false;
|
||||
} else {
|
||||
if (!input_->Skip(count)) return false;
|
||||
limit_ -= count;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int64 LimitingInputStream::ByteCount() const {
|
||||
if (limit_ < 0) {
|
||||
return input_->ByteCount() + limit_ - prior_bytes_read_;
|
||||
} else {
|
||||
return input_->ByteCount() - prior_bytes_read_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
} // namespace io
|
||||
|
||||
@@ -40,18 +40,20 @@
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which reads from a file descriptor.
|
||||
@@ -60,7 +62,7 @@ namespace io {
|
||||
// The latter will introduce an extra layer of buffering, harming performance.
|
||||
// Also, it's conceivable that FileInputStream could someday be enhanced
|
||||
// to use zero-copy file descriptors on OSs which support them.
|
||||
class LIBPROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream {
|
||||
class PROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
@@ -84,27 +86,27 @@ class LIBPROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream {
|
||||
// errno from that error. Otherwise, this is zero. Once an error
|
||||
// occurs, the stream is broken and all subsequent operations will
|
||||
// fail.
|
||||
int GetErrno() { return copying_input_.GetErrno(); }
|
||||
int GetErrno() const { return copying_input_.GetErrno(); }
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
class LIBPROTOBUF_EXPORT CopyingFileInputStream : public CopyingInputStream {
|
||||
class PROTOBUF_EXPORT CopyingFileInputStream : public CopyingInputStream {
|
||||
public:
|
||||
CopyingFileInputStream(int file_descriptor);
|
||||
~CopyingFileInputStream();
|
||||
~CopyingFileInputStream() override;
|
||||
|
||||
bool Close();
|
||||
void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
|
||||
int GetErrno() { return errno_; }
|
||||
int GetErrno() const { return errno_; }
|
||||
|
||||
// implements CopyingInputStream ---------------------------------
|
||||
int Read(void* buffer, int size);
|
||||
int Skip(int count);
|
||||
int Read(void* buffer, int size) override;
|
||||
int Skip(int count) override;
|
||||
|
||||
private:
|
||||
// The file descriptor.
|
||||
@@ -137,25 +139,21 @@ class LIBPROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream {
|
||||
// harming performance. Also, it's conceivable that FileOutputStream could
|
||||
// someday be enhanced to use zero-copy file descriptors on OSs which
|
||||
// support them.
|
||||
class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream {
|
||||
class PROTOBUF_EXPORT FileOutputStream : public CopyingOutputStreamAdaptor {
|
||||
public:
|
||||
// Creates a stream that writes to the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
// that should be returned by Next(). Otherwise, a reasonable default
|
||||
// is used.
|
||||
explicit FileOutputStream(int file_descriptor, int block_size = -1);
|
||||
~FileOutputStream();
|
||||
|
||||
~FileOutputStream() override;
|
||||
|
||||
// Flushes any buffers and closes the underlying file. Returns false if
|
||||
// an error occurs during the process; use GetErrno() to examine the error.
|
||||
// Even if an error occurs, the file descriptor is closed when this returns.
|
||||
bool Close();
|
||||
|
||||
// Flushes FileOutputStream's buffers but does not close the
|
||||
// underlying file. No special measures are taken to ensure that
|
||||
// underlying operating system file object is synchronized to disk.
|
||||
bool Flush();
|
||||
|
||||
// By default, the file descriptor is not closed when the stream is
|
||||
// destroyed. Call SetCloseOnDelete(true) to change that. WARNING:
|
||||
// This leaves no way for the caller to detect if close() fails. If
|
||||
@@ -167,25 +165,20 @@ class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream {
|
||||
// errno from that error. Otherwise, this is zero. Once an error
|
||||
// occurs, the stream is broken and all subsequent operations will
|
||||
// fail.
|
||||
int GetErrno() { return copying_output_.GetErrno(); }
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
int GetErrno() const { return copying_output_.GetErrno(); }
|
||||
|
||||
private:
|
||||
class LIBPROTOBUF_EXPORT CopyingFileOutputStream : public CopyingOutputStream {
|
||||
class PROTOBUF_EXPORT CopyingFileOutputStream : public CopyingOutputStream {
|
||||
public:
|
||||
CopyingFileOutputStream(int file_descriptor);
|
||||
~CopyingFileOutputStream();
|
||||
~CopyingFileOutputStream() override;
|
||||
|
||||
bool Close();
|
||||
void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
|
||||
int GetErrno() { return errno_; }
|
||||
int GetErrno() const { return errno_; }
|
||||
|
||||
// implements CopyingOutputStream --------------------------------
|
||||
bool Write(const void* buffer, int size);
|
||||
bool Write(const void* buffer, int size) override;
|
||||
|
||||
private:
|
||||
// The file descriptor.
|
||||
@@ -200,7 +193,6 @@ class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream {
|
||||
};
|
||||
|
||||
CopyingFileOutputStream copying_output_;
|
||||
CopyingOutputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileOutputStream);
|
||||
};
|
||||
@@ -211,7 +203,7 @@ class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream {
|
||||
//
|
||||
// Note that for reading files (or anything represented by a file descriptor),
|
||||
// FileInputStream is more efficient.
|
||||
class LIBPROTOBUF_EXPORT IstreamInputStream : public ZeroCopyInputStream {
|
||||
class PROTOBUF_EXPORT IstreamInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given C++ istream.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
@@ -220,19 +212,19 @@ class LIBPROTOBUF_EXPORT IstreamInputStream : public ZeroCopyInputStream {
|
||||
explicit IstreamInputStream(std::istream* stream, int block_size = -1);
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
class LIBPROTOBUF_EXPORT CopyingIstreamInputStream : public CopyingInputStream {
|
||||
class PROTOBUF_EXPORT CopyingIstreamInputStream : public CopyingInputStream {
|
||||
public:
|
||||
CopyingIstreamInputStream(std::istream* input);
|
||||
~CopyingIstreamInputStream();
|
||||
~CopyingIstreamInputStream() override;
|
||||
|
||||
// implements CopyingInputStream ---------------------------------
|
||||
int Read(void* buffer, int size);
|
||||
int Read(void* buffer, int size) override;
|
||||
// (We use the default implementation of Skip().)
|
||||
|
||||
private:
|
||||
@@ -254,28 +246,29 @@ class LIBPROTOBUF_EXPORT IstreamInputStream : public ZeroCopyInputStream {
|
||||
//
|
||||
// Note that for writing files (or anything represented by a file descriptor),
|
||||
// FileOutputStream is more efficient.
|
||||
class LIBPROTOBUF_EXPORT OstreamOutputStream : public ZeroCopyOutputStream {
|
||||
class PROTOBUF_EXPORT OstreamOutputStream : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Creates a stream that writes to the given C++ ostream.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
// that should be returned by Next(). Otherwise, a reasonable default
|
||||
// is used.
|
||||
explicit OstreamOutputStream(std::ostream* stream, int block_size = -1);
|
||||
~OstreamOutputStream();
|
||||
~OstreamOutputStream() override;
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
bool Next(void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
class LIBPROTOBUF_EXPORT CopyingOstreamOutputStream : public CopyingOutputStream {
|
||||
class PROTOBUF_EXPORT CopyingOstreamOutputStream
|
||||
: public CopyingOutputStream {
|
||||
public:
|
||||
CopyingOstreamOutputStream(std::ostream* output);
|
||||
~CopyingOstreamOutputStream();
|
||||
~CopyingOstreamOutputStream() override;
|
||||
|
||||
// implements CopyingOutputStream --------------------------------
|
||||
bool Write(const void* buffer, int size);
|
||||
bool Write(const void* buffer, int size) override;
|
||||
|
||||
private:
|
||||
// The stream.
|
||||
@@ -299,17 +292,18 @@ class LIBPROTOBUF_EXPORT OstreamOutputStream : public ZeroCopyOutputStream {
|
||||
// ConcatenatingInputStream may do odd things. It is suggested that you do
|
||||
// not use ConcatenatingInputStream on streams that might produce read errors
|
||||
// other than end-of-stream.
|
||||
class LIBPROTOBUF_EXPORT ConcatenatingInputStream : public ZeroCopyInputStream {
|
||||
class PROTOBUF_EXPORT ConcatenatingInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
// All streams passed in as well as the array itself must remain valid
|
||||
// until the ConcatenatingInputStream is destroyed.
|
||||
ConcatenatingInputStream(ZeroCopyInputStream* const streams[], int count);
|
||||
~ConcatenatingInputStream() override = default;
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -317,39 +311,17 @@ class LIBPROTOBUF_EXPORT ConcatenatingInputStream : public ZeroCopyInputStream {
|
||||
// decremented.
|
||||
ZeroCopyInputStream* const* streams_;
|
||||
int stream_count_;
|
||||
int64 bytes_retired_; // Bytes read from previous streams.
|
||||
int64_t bytes_retired_; // Bytes read from previous streams.
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ConcatenatingInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which wraps some other stream and limits it to
|
||||
// a particular byte count.
|
||||
class LIBPROTOBUF_EXPORT LimitingInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
LimitingInputStream(ZeroCopyInputStream* input, int64 limit);
|
||||
~LimitingInputStream();
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
|
||||
private:
|
||||
ZeroCopyInputStream* input_;
|
||||
int64 limit_; // Decreases as we go, becomes negative if we overshoot.
|
||||
int64 prior_bytes_read_; // Bytes read on underlying stream at construction
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
#include <google/protobuf/stubs/casts.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/casts.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
namespace google {
|
||||
@@ -55,14 +55,12 @@ static const int kDefaultBlockSize = 8192;
|
||||
|
||||
// ===================================================================
|
||||
|
||||
ArrayInputStream::ArrayInputStream(const void* data, int size,
|
||||
int block_size)
|
||||
: data_(reinterpret_cast<const uint8*>(data)),
|
||||
size_(size),
|
||||
block_size_(block_size > 0 ? block_size : size),
|
||||
position_(0),
|
||||
last_returned_size_(0) {
|
||||
}
|
||||
ArrayInputStream::ArrayInputStream(const void* data, int size, int block_size)
|
||||
: data_(reinterpret_cast<const uint8_t*>(data)),
|
||||
size_(size),
|
||||
block_size_(block_size > 0 ? block_size : size),
|
||||
position_(0),
|
||||
last_returned_size_(0) {}
|
||||
|
||||
bool ArrayInputStream::Next(const void** data, int* size) {
|
||||
if (position_ < size_) {
|
||||
@@ -73,7 +71,7 @@ bool ArrayInputStream::Next(const void** data, int* size) {
|
||||
return true;
|
||||
} else {
|
||||
// We're at the end of the array.
|
||||
last_returned_size_ = 0; // Don't let caller back up.
|
||||
last_returned_size_ = 0; // Don't let caller back up.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -89,7 +87,7 @@ void ArrayInputStream::BackUp(int count) {
|
||||
|
||||
bool ArrayInputStream::Skip(int count) {
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
last_returned_size_ = 0; // Don't let caller back up.
|
||||
last_returned_size_ = 0; // Don't let caller back up.
|
||||
if (count > size_ - position_) {
|
||||
position_ = size_;
|
||||
return false;
|
||||
@@ -99,20 +97,17 @@ bool ArrayInputStream::Skip(int count) {
|
||||
}
|
||||
}
|
||||
|
||||
int64 ArrayInputStream::ByteCount() const {
|
||||
return position_;
|
||||
}
|
||||
int64_t ArrayInputStream::ByteCount() const { return position_; }
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size)
|
||||
: data_(reinterpret_cast<uint8*>(data)),
|
||||
size_(size),
|
||||
block_size_(block_size > 0 ? block_size : size),
|
||||
position_(0),
|
||||
last_returned_size_(0) {
|
||||
}
|
||||
: data_(reinterpret_cast<uint8_t*>(data)),
|
||||
size_(size),
|
||||
block_size_(block_size > 0 ? block_size : size),
|
||||
position_(0),
|
||||
last_returned_size_(0) {}
|
||||
|
||||
bool ArrayOutputStream::Next(void** data, int* size) {
|
||||
if (position_ < size_) {
|
||||
@@ -123,7 +118,7 @@ bool ArrayOutputStream::Next(void** data, int* size) {
|
||||
return true;
|
||||
} else {
|
||||
// We're at the end of the array.
|
||||
last_returned_size_ = 0; // Don't let caller back up.
|
||||
last_returned_size_ = 0; // Don't let caller back up.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -137,41 +132,33 @@ void ArrayOutputStream::BackUp(int count) {
|
||||
last_returned_size_ = 0; // Don't let caller back up further.
|
||||
}
|
||||
|
||||
int64 ArrayOutputStream::ByteCount() const {
|
||||
return position_;
|
||||
}
|
||||
int64_t ArrayOutputStream::ByteCount() const { return position_; }
|
||||
|
||||
// ===================================================================
|
||||
|
||||
StringOutputStream::StringOutputStream(string* target)
|
||||
: target_(target) {
|
||||
}
|
||||
StringOutputStream::StringOutputStream(std::string* target) : target_(target) {}
|
||||
|
||||
bool StringOutputStream::Next(void** data, int* size) {
|
||||
GOOGLE_CHECK(target_ != NULL);
|
||||
int old_size = target_->size();
|
||||
size_t old_size = target_->size();
|
||||
|
||||
// Grow the string.
|
||||
size_t new_size;
|
||||
if (old_size < target_->capacity()) {
|
||||
// Resize the string to match its capacity, since we can get away
|
||||
// without a memory allocation this way.
|
||||
STLStringResizeUninitialized(target_, target_->capacity());
|
||||
new_size = target_->capacity();
|
||||
} else {
|
||||
// Size has reached capacity, try to double the size.
|
||||
if (old_size > std::numeric_limits<int>::max() / 2) {
|
||||
// Can not double the size otherwise it is going to cause integer
|
||||
// overflow in the expression below: old_size * 2 ";
|
||||
GOOGLE_LOG(ERROR) << "Cannot allocate buffer larger than kint32max for "
|
||||
<< "StringOutputStream.";
|
||||
return false;
|
||||
}
|
||||
// Double the size, also make sure that the new size is at least
|
||||
// kMinimumSize.
|
||||
STLStringResizeUninitialized(
|
||||
target_,
|
||||
std::max(old_size * 2,
|
||||
kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness.
|
||||
// Size has reached capacity, try to double it.
|
||||
new_size = old_size * 2;
|
||||
}
|
||||
// Avoid integer overflow in returned '*size'.
|
||||
new_size = std::min(new_size, old_size + std::numeric_limits<int>::max());
|
||||
// Increase the size, also make sure that it is at least kMinimumSize.
|
||||
STLStringResizeUninitialized(
|
||||
target_,
|
||||
std::max(new_size,
|
||||
kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness.
|
||||
|
||||
*data = mutable_string_data(target_) + old_size;
|
||||
*size = target_->size() - old_size;
|
||||
@@ -181,27 +168,23 @@ bool StringOutputStream::Next(void** data, int* size) {
|
||||
void StringOutputStream::BackUp(int count) {
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
GOOGLE_CHECK(target_ != NULL);
|
||||
GOOGLE_CHECK_LE(count, target_->size());
|
||||
GOOGLE_CHECK_LE(static_cast<size_t>(count), target_->size());
|
||||
target_->resize(target_->size() - count);
|
||||
}
|
||||
|
||||
int64 StringOutputStream::ByteCount() const {
|
||||
int64_t StringOutputStream::ByteCount() const {
|
||||
GOOGLE_CHECK(target_ != NULL);
|
||||
return target_->size();
|
||||
}
|
||||
|
||||
void StringOutputStream::SetString(string* target) {
|
||||
target_ = target;
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
int CopyingInputStream::Skip(int count) {
|
||||
char junk[4096];
|
||||
int skipped = 0;
|
||||
while (skipped < count) {
|
||||
int bytes =
|
||||
Read(junk, std::min(count - skipped, implicit_cast<int>(sizeof(junk))));
|
||||
int bytes = Read(junk, std::min(count - skipped,
|
||||
implicit_cast<int>(sizeof(junk))));
|
||||
if (bytes <= 0) {
|
||||
// EOF or read error.
|
||||
return skipped;
|
||||
@@ -213,14 +196,13 @@ int CopyingInputStream::Skip(int count) {
|
||||
|
||||
CopyingInputStreamAdaptor::CopyingInputStreamAdaptor(
|
||||
CopyingInputStream* copying_stream, int block_size)
|
||||
: copying_stream_(copying_stream),
|
||||
owns_copying_stream_(false),
|
||||
failed_(false),
|
||||
position_(0),
|
||||
buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
|
||||
buffer_used_(0),
|
||||
backup_bytes_(0) {
|
||||
}
|
||||
: copying_stream_(copying_stream),
|
||||
owns_copying_stream_(false),
|
||||
failed_(false),
|
||||
position_(0),
|
||||
buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
|
||||
buffer_used_(0),
|
||||
backup_bytes_(0) {}
|
||||
|
||||
CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() {
|
||||
if (owns_copying_stream_) {
|
||||
@@ -264,12 +246,11 @@ bool CopyingInputStreamAdaptor::Next(const void** data, int* size) {
|
||||
|
||||
void CopyingInputStreamAdaptor::BackUp(int count) {
|
||||
GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL)
|
||||
<< " BackUp() can only be called after Next().";
|
||||
<< " BackUp() can only be called after Next().";
|
||||
GOOGLE_CHECK_LE(count, buffer_used_)
|
||||
<< " Can't back up over more bytes than were returned by the last call"
|
||||
" to Next().";
|
||||
GOOGLE_CHECK_GE(count, 0)
|
||||
<< " Parameter to BackUp() can't be negative.";
|
||||
<< " Can't back up over more bytes than were returned by the last call"
|
||||
" to Next().";
|
||||
GOOGLE_CHECK_GE(count, 0) << " Parameter to BackUp() can't be negative.";
|
||||
|
||||
backup_bytes_ = count;
|
||||
}
|
||||
@@ -297,13 +278,13 @@ bool CopyingInputStreamAdaptor::Skip(int count) {
|
||||
return skipped == count;
|
||||
}
|
||||
|
||||
int64 CopyingInputStreamAdaptor::ByteCount() const {
|
||||
int64_t CopyingInputStreamAdaptor::ByteCount() const {
|
||||
return position_ - backup_bytes_;
|
||||
}
|
||||
|
||||
void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() {
|
||||
if (buffer_.get() == NULL) {
|
||||
buffer_.reset(new uint8[buffer_size_]);
|
||||
buffer_.reset(new uint8_t[buffer_size_]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,13 +298,12 @@ void CopyingInputStreamAdaptor::FreeBuffer() {
|
||||
|
||||
CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor(
|
||||
CopyingOutputStream* copying_stream, int block_size)
|
||||
: copying_stream_(copying_stream),
|
||||
owns_copying_stream_(false),
|
||||
failed_(false),
|
||||
position_(0),
|
||||
buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
|
||||
buffer_used_(0) {
|
||||
}
|
||||
: copying_stream_(copying_stream),
|
||||
owns_copying_stream_(false),
|
||||
failed_(false),
|
||||
position_(0),
|
||||
buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
|
||||
buffer_used_(0) {}
|
||||
|
||||
CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() {
|
||||
WriteBuffer();
|
||||
@@ -332,9 +312,7 @@ CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() {
|
||||
}
|
||||
}
|
||||
|
||||
bool CopyingOutputStreamAdaptor::Flush() {
|
||||
return WriteBuffer();
|
||||
}
|
||||
bool CopyingOutputStreamAdaptor::Flush() { return WriteBuffer(); }
|
||||
|
||||
bool CopyingOutputStreamAdaptor::Next(void** data, int* size) {
|
||||
if (buffer_used_ == buffer_size_) {
|
||||
@@ -352,18 +330,49 @@ bool CopyingOutputStreamAdaptor::Next(void** data, int* size) {
|
||||
void CopyingOutputStreamAdaptor::BackUp(int count) {
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
GOOGLE_CHECK_EQ(buffer_used_, buffer_size_)
|
||||
<< " BackUp() can only be called after Next().";
|
||||
<< " BackUp() can only be called after Next().";
|
||||
GOOGLE_CHECK_LE(count, buffer_used_)
|
||||
<< " Can't back up over more bytes than were returned by the last call"
|
||||
" to Next().";
|
||||
<< " Can't back up over more bytes than were returned by the last call"
|
||||
" to Next().";
|
||||
|
||||
buffer_used_ -= count;
|
||||
}
|
||||
|
||||
int64 CopyingOutputStreamAdaptor::ByteCount() const {
|
||||
int64_t CopyingOutputStreamAdaptor::ByteCount() const {
|
||||
return position_ + buffer_used_;
|
||||
}
|
||||
|
||||
bool CopyingOutputStreamAdaptor::WriteAliasedRaw(const void* data, int size) {
|
||||
if (size >= buffer_size_) {
|
||||
if (!Flush() || !copying_stream_->Write(data, size)) {
|
||||
return false;
|
||||
}
|
||||
GOOGLE_DCHECK_EQ(buffer_used_, 0);
|
||||
position_ += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
void* out;
|
||||
int out_size;
|
||||
while (true) {
|
||||
if (!Next(&out, &out_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (size <= out_size) {
|
||||
std::memcpy(out, data, size);
|
||||
BackUp(out_size - size);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::memcpy(out, data, out_size);
|
||||
data = static_cast<const char*>(data) + out_size;
|
||||
size -= out_size;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CopyingOutputStreamAdaptor::WriteBuffer() {
|
||||
if (failed_) {
|
||||
// Already failed on a previous write.
|
||||
@@ -385,7 +394,7 @@ bool CopyingOutputStreamAdaptor::WriteBuffer() {
|
||||
|
||||
void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() {
|
||||
if (buffer_ == NULL) {
|
||||
buffer_.reset(new uint8[buffer_size_]);
|
||||
buffer_.reset(new uint8_t[buffer_size_]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,6 +403,63 @@ void CopyingOutputStreamAdaptor::FreeBuffer() {
|
||||
buffer_.reset();
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
LimitingInputStream::LimitingInputStream(ZeroCopyInputStream* input,
|
||||
int64_t limit)
|
||||
: input_(input), limit_(limit) {
|
||||
prior_bytes_read_ = input_->ByteCount();
|
||||
}
|
||||
|
||||
LimitingInputStream::~LimitingInputStream() {
|
||||
// If we overshot the limit, back up.
|
||||
if (limit_ < 0) input_->BackUp(-limit_);
|
||||
}
|
||||
|
||||
bool LimitingInputStream::Next(const void** data, int* size) {
|
||||
if (limit_ <= 0) return false;
|
||||
if (!input_->Next(data, size)) return false;
|
||||
|
||||
limit_ -= *size;
|
||||
if (limit_ < 0) {
|
||||
// We overshot the limit. Reduce *size to hide the rest of the buffer.
|
||||
*size += limit_;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LimitingInputStream::BackUp(int count) {
|
||||
if (limit_ < 0) {
|
||||
input_->BackUp(count - limit_);
|
||||
limit_ = count;
|
||||
} else {
|
||||
input_->BackUp(count);
|
||||
limit_ += count;
|
||||
}
|
||||
}
|
||||
|
||||
bool LimitingInputStream::Skip(int count) {
|
||||
if (count > limit_) {
|
||||
if (limit_ < 0) return false;
|
||||
input_->Skip(limit_);
|
||||
limit_ = 0;
|
||||
return false;
|
||||
} else {
|
||||
if (!input_->Skip(count)) return false;
|
||||
limit_ -= count;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t LimitingInputStream::ByteCount() const {
|
||||
if (limit_ < 0) {
|
||||
return input_->ByteCount() + limit_ - prior_bytes_read_;
|
||||
} else {
|
||||
return input_->ByteCount() - prior_bytes_read_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
} // namespace io
|
||||
|
||||
@@ -44,18 +44,19 @@
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
||||
|
||||
#include <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
#include <string>
|
||||
|
||||
#include <iosfwd>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/callback.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
@@ -63,7 +64,7 @@ namespace io {
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream backed by an in-memory array of bytes.
|
||||
class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream {
|
||||
class PROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Create an InputStream that returns the bytes pointed to by "data".
|
||||
// "data" remains the property of the caller but must remain valid until
|
||||
@@ -73,22 +74,23 @@ class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream {
|
||||
// useful for testing; in production you would probably never want to set
|
||||
// it.
|
||||
ArrayInputStream(const void* data, int size, int block_size = -1);
|
||||
~ArrayInputStream() override = default;
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
|
||||
private:
|
||||
const uint8* const data_; // The byte array.
|
||||
const uint8_t* const data_; // The byte array.
|
||||
const int size_; // Total size of the array.
|
||||
const int block_size_; // How many bytes to return at a time.
|
||||
|
||||
int position_;
|
||||
int last_returned_size_; // How many bytes we returned last time Next()
|
||||
// was called (used for error checking only).
|
||||
int last_returned_size_; // How many bytes we returned last time Next()
|
||||
// was called (used for error checking only).
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream);
|
||||
};
|
||||
@@ -96,7 +98,7 @@ class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream {
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream backed by an in-memory array of bytes.
|
||||
class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream {
|
||||
class PROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Create an OutputStream that writes to the bytes pointed to by "data".
|
||||
// "data" remains the property of the caller but must remain valid until
|
||||
@@ -106,20 +108,21 @@ class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream {
|
||||
// useful for testing; in production you would probably never want to set
|
||||
// it.
|
||||
ArrayOutputStream(void* data, int size, int block_size = -1);
|
||||
~ArrayOutputStream() override = default;
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
bool Next(void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
uint8* const data_; // The byte array.
|
||||
const int size_; // Total size of the array.
|
||||
const int block_size_; // How many bytes to return at a time.
|
||||
uint8_t* const data_; // The byte array.
|
||||
const int size_; // Total size of the array.
|
||||
const int block_size_; // How many bytes to return at a time.
|
||||
|
||||
int position_;
|
||||
int last_returned_size_; // How many bytes we returned last time Next()
|
||||
// was called (used for error checking only).
|
||||
int last_returned_size_; // How many bytes we returned last time Next()
|
||||
// was called (used for error checking only).
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream);
|
||||
};
|
||||
@@ -127,7 +130,7 @@ class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream {
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream which appends bytes to a string.
|
||||
class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream {
|
||||
class PROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Create a StringOutputStream which appends bytes to the given string.
|
||||
// The string remains property of the caller, but it is mutated in arbitrary
|
||||
@@ -138,20 +141,18 @@ class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream {
|
||||
// Hint: If you call target->reserve(n) before creating the stream,
|
||||
// the first call to Next() will return at least n bytes of buffer
|
||||
// space.
|
||||
explicit StringOutputStream(string* target);
|
||||
explicit StringOutputStream(std::string* target);
|
||||
~StringOutputStream() override = default;
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
protected:
|
||||
void SetString(string* target);
|
||||
bool Next(void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
static const int kMinimumSize = 16;
|
||||
static constexpr size_t kMinimumSize = 16;
|
||||
|
||||
string* target_;
|
||||
std::string* target_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream);
|
||||
};
|
||||
@@ -173,7 +174,7 @@ class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream {
|
||||
// CopyingInputStream implementations should avoid buffering if possible.
|
||||
// CopyingInputStreamAdaptor does its own buffering and will read data
|
||||
// in large blocks.
|
||||
class LIBPROTOBUF_EXPORT CopyingInputStream {
|
||||
class PROTOBUF_EXPORT CopyingInputStream {
|
||||
public:
|
||||
virtual ~CopyingInputStream() {}
|
||||
|
||||
@@ -199,7 +200,7 @@ class LIBPROTOBUF_EXPORT CopyingInputStream {
|
||||
// If you want to read from file descriptors or C++ istreams, this is
|
||||
// already implemented for you: use FileInputStream or IstreamInputStream
|
||||
// respectively.
|
||||
class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream {
|
||||
class PROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given CopyingInputStream.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
@@ -208,17 +209,17 @@ class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream
|
||||
// copying_stream unless SetOwnsCopyingStream(true) is called.
|
||||
explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream,
|
||||
int block_size = -1);
|
||||
~CopyingInputStreamAdaptor();
|
||||
~CopyingInputStreamAdaptor() override;
|
||||
|
||||
// Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to
|
||||
// delete the underlying CopyingInputStream when it is destroyed.
|
||||
void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
private:
|
||||
// Insures that buffer_ is not NULL.
|
||||
@@ -230,16 +231,16 @@ class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream
|
||||
CopyingInputStream* copying_stream_;
|
||||
bool owns_copying_stream_;
|
||||
|
||||
// True if we have seen a permenant error from the underlying stream.
|
||||
// True if we have seen a permanent error from the underlying stream.
|
||||
bool failed_;
|
||||
|
||||
// The current position of copying_stream_, relative to the point where
|
||||
// we started reading.
|
||||
int64 position_;
|
||||
int64_t position_;
|
||||
|
||||
// Data is read into this buffer. It may be NULL if no buffer is currently
|
||||
// in use. Otherwise, it points to an array of size buffer_size_.
|
||||
google::protobuf::scoped_array<uint8> buffer_;
|
||||
std::unique_ptr<uint8_t[]> buffer_;
|
||||
const int buffer_size_;
|
||||
|
||||
// Number of valid bytes currently in the buffer (i.e. the size last
|
||||
@@ -267,7 +268,7 @@ class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream
|
||||
// CopyingOutputStream implementations should avoid buffering if possible.
|
||||
// CopyingOutputStreamAdaptor does its own buffering and will write data
|
||||
// in large blocks.
|
||||
class LIBPROTOBUF_EXPORT CopyingOutputStream {
|
||||
class PROTOBUF_EXPORT CopyingOutputStream {
|
||||
public:
|
||||
virtual ~CopyingOutputStream() {}
|
||||
|
||||
@@ -283,7 +284,7 @@ class LIBPROTOBUF_EXPORT CopyingOutputStream {
|
||||
// If you want to write to file descriptors or C++ ostreams, this is
|
||||
// already implemented for you: use FileOutputStream or OstreamOutputStream
|
||||
// respectively.
|
||||
class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream {
|
||||
class PROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Creates a stream that writes to the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
@@ -291,7 +292,7 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea
|
||||
// is used.
|
||||
explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream,
|
||||
int block_size = -1);
|
||||
~CopyingOutputStreamAdaptor();
|
||||
~CopyingOutputStreamAdaptor() override;
|
||||
|
||||
// Writes all pending data to the underlying stream. Returns false if a
|
||||
// write error occurred on the underlying stream. (The underlying
|
||||
@@ -303,9 +304,11 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea
|
||||
void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
bool Next(void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
bool WriteAliasedRaw(const void* data, int size) override;
|
||||
bool AllowsAliasing() const override { return true; }
|
||||
|
||||
private:
|
||||
// Write the current buffer, if it is present.
|
||||
@@ -319,16 +322,16 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea
|
||||
CopyingOutputStream* copying_stream_;
|
||||
bool owns_copying_stream_;
|
||||
|
||||
// True if we have seen a permenant error from the underlying stream.
|
||||
// True if we have seen a permanent error from the underlying stream.
|
||||
bool failed_;
|
||||
|
||||
// The current position of copying_stream_, relative to the point where
|
||||
// we started writing.
|
||||
int64 position_;
|
||||
int64_t position_;
|
||||
|
||||
// Data is written from this buffer. It may be NULL if no buffer is
|
||||
// currently in use. Otherwise, it points to an array of size buffer_size_.
|
||||
google::protobuf::scoped_array<uint8> buffer_;
|
||||
std::unique_ptr<uint8_t[]> buffer_;
|
||||
const int buffer_size_;
|
||||
|
||||
// Number of valid bytes currently in the buffer (i.e. the size last
|
||||
@@ -339,6 +342,31 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which wraps some other stream and limits it to
|
||||
// a particular byte count.
|
||||
class PROTOBUF_EXPORT LimitingInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
LimitingInputStream(ZeroCopyInputStream* input, int64_t limit);
|
||||
~LimitingInputStream() override;
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size) override;
|
||||
void BackUp(int count) override;
|
||||
bool Skip(int count) override;
|
||||
int64_t ByteCount() const override;
|
||||
|
||||
|
||||
private:
|
||||
ZeroCopyInputStream* input_;
|
||||
int64_t limit_; // Decreases as we go, becomes negative if we overshoot.
|
||||
int64_t prior_bytes_read_; // Bytes read on underlying stream at construction
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream);
|
||||
};
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// mutable_string_data() and as_string_data() are workarounds to improve
|
||||
@@ -356,31 +384,25 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea
|
||||
// Return a pointer to mutable characters underlying the given string. The
|
||||
// return value is valid until the next time the string is resized. We
|
||||
// trust the caller to treat the return value as an array of length s->size().
|
||||
inline char* mutable_string_data(string* s) {
|
||||
#ifdef LANG_CXX11
|
||||
inline char* mutable_string_data(std::string* s) {
|
||||
// This should be simpler & faster than string_as_array() because the latter
|
||||
// is guaranteed to return NULL when *s is empty, so it has to check for that.
|
||||
return &(*s)[0];
|
||||
#else
|
||||
return string_as_array(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
// as_string_data(s) is equivalent to
|
||||
// ({ char* p = mutable_string_data(s); make_pair(p, p != NULL); })
|
||||
// Sometimes it's faster: in some scenarios p cannot be NULL, and then the
|
||||
// code can avoid that check.
|
||||
inline std::pair<char*, bool> as_string_data(string* s) {
|
||||
char *p = mutable_string_data(s);
|
||||
#ifdef LANG_CXX11
|
||||
inline std::pair<char*, bool> as_string_data(std::string* s) {
|
||||
char* p = mutable_string_data(s);
|
||||
return std::make_pair(p, true);
|
||||
#else
|
||||
return std::make_pair(p, p != NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
||||
|
||||
+4
-5
@@ -28,15 +28,14 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/util/internal/error_listener.h>
|
||||
#include <google/protobuf/map.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace util {
|
||||
namespace converter {
|
||||
namespace internal {
|
||||
|
||||
void* const kGlobalEmptyTable[kGlobalEmptyTableSize] = {nullptr};
|
||||
|
||||
} // namespace converter
|
||||
} // namespace util
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
+588
-428
File diff suppressed because it is too large
Load Diff
+53
-33
@@ -34,10 +34,16 @@
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/map_entry_lite.h>
|
||||
#include <google/protobuf/map_type_handler.h>
|
||||
#include <google/protobuf/metadata.h>
|
||||
#include <google/protobuf/port.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
@@ -45,11 +51,13 @@ class Arena;
|
||||
namespace internal {
|
||||
template <typename Derived, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapField;
|
||||
}
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
@@ -70,40 +78,52 @@ namespace internal {
|
||||
// field.
|
||||
//
|
||||
// cpp type | proto type | in-memory type | MapEntry accessor type
|
||||
// int32 TYPE_INT32 int32 int32
|
||||
// int32 TYPE_FIXED32 int32 int32
|
||||
// int32_t TYPE_INT32 int32_t int32_t
|
||||
// int32_t TYPE_FIXED32 int32_t int32_t
|
||||
// string TYPE_STRING ArenaStringPtr string
|
||||
// FooEnum TYPE_ENUM int int
|
||||
// FooMessage TYPE_MESSAGE FooMessage* FooMessage
|
||||
//
|
||||
// The in-memory types of primitive types can be inferred from its proto type,
|
||||
// while we need to explicitly specify the cpp type if proto type is
|
||||
// TYPE_MESSAGE to infer the in-memory type. Moreover, default_enum_value is
|
||||
// used to initialize enum field in proto2.
|
||||
// TYPE_MESSAGE to infer the in-memory type.
|
||||
template <typename Derived, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
|
||||
class MapEntry
|
||||
: public MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
|
||||
kValueFieldType, default_enum_value> {
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
class MapEntry : public MapEntryImpl<Derived, Message, Key, Value,
|
||||
kKeyFieldType, kValueFieldType> {
|
||||
public:
|
||||
MapEntry() : _internal_metadata_(NULL) {}
|
||||
constexpr MapEntry() : _internal_metadata_() {}
|
||||
explicit MapEntry(Arena* arena)
|
||||
: MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
|
||||
kValueFieldType, default_enum_value>(arena),
|
||||
kValueFieldType>(arena),
|
||||
_internal_metadata_(arena) {}
|
||||
~MapEntry() {
|
||||
Message::_internal_metadata_.template Delete<UnknownFieldSet>();
|
||||
_internal_metadata_.Delete<UnknownFieldSet>();
|
||||
}
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
|
||||
InternalMetadataWithArena _internal_metadata_;
|
||||
typedef typename MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
|
||||
kValueFieldType>::KeyTypeHandler KeyTypeHandler;
|
||||
typedef
|
||||
typename MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
|
||||
kValueFieldType>::ValueTypeHandler ValueTypeHandler;
|
||||
size_t SpaceUsedLong() const override {
|
||||
size_t size = sizeof(Derived);
|
||||
size += KeyTypeHandler::SpaceUsedInMapEntryLong(this->key_);
|
||||
size += ValueTypeHandler::SpaceUsedInMapEntryLong(this->value_);
|
||||
return size;
|
||||
}
|
||||
|
||||
InternalMetadata _internal_metadata_;
|
||||
|
||||
private:
|
||||
friend class ::google::protobuf::Arena;
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::Arena;
|
||||
template <typename C, typename K, typename V,
|
||||
WireFormatLite::FieldType k_wire_type, WireFormatLite::FieldType,
|
||||
int default_enum>
|
||||
WireFormatLite::FieldType k_wire_type, WireFormatLite::FieldType>
|
||||
friend class internal::MapField;
|
||||
friend class internal::GeneratedMessageReflection;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
|
||||
};
|
||||
@@ -111,30 +131,30 @@ class MapEntry
|
||||
// Specialization for the full runtime
|
||||
template <typename Derived, typename Key, typename Value,
|
||||
WireFormatLite::FieldType kKeyFieldType,
|
||||
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
|
||||
struct MapEntryHelper<MapEntry<Derived, Key, Value, kKeyFieldType,
|
||||
kValueFieldType, default_enum_value> >
|
||||
: MapEntryHelper<MapEntryLite<Derived, Key, Value, kKeyFieldType,
|
||||
kValueFieldType, default_enum_value> > {
|
||||
WireFormatLite::FieldType kValueFieldType>
|
||||
struct MapEntryHelper<
|
||||
MapEntry<Derived, Key, Value, kKeyFieldType, kValueFieldType> >
|
||||
: MapEntryHelper<
|
||||
MapEntryLite<Derived, Key, Value, kKeyFieldType, kValueFieldType> > {
|
||||
explicit MapEntryHelper(const MapPair<Key, Value>& map_pair)
|
||||
: MapEntryHelper<MapEntryLite<Derived, Key, Value, kKeyFieldType,
|
||||
kValueFieldType, default_enum_value> >(
|
||||
: MapEntryHelper<
|
||||
MapEntryLite<Derived, Key, Value, kKeyFieldType, kValueFieldType> >(
|
||||
map_pair) {}
|
||||
};
|
||||
|
||||
template <typename Derived, typename K, typename V,
|
||||
WireFormatLite::FieldType key, WireFormatLite::FieldType value,
|
||||
int default_enum>
|
||||
struct DeconstructMapEntry<MapEntry<Derived, K, V, key, value, default_enum> > {
|
||||
WireFormatLite::FieldType key, WireFormatLite::FieldType value>
|
||||
struct DeconstructMapEntry<MapEntry<Derived, K, V, key, value> > {
|
||||
typedef K Key;
|
||||
typedef V Value;
|
||||
static const WireFormatLite::FieldType kKeyFieldType = key;
|
||||
static const WireFormatLite::FieldType kValueFieldType = value;
|
||||
static const int default_enum_value = default_enum;
|
||||
static constexpr WireFormatLite::FieldType kKeyFieldType = key;
|
||||
static constexpr WireFormatLite::FieldType kValueFieldType = value;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_MAP_ENTRY_H__
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user