File indexing completed on 2025-01-31 10:12:28
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef GOOGLE_PROTOBUF_VARINT_SHUFFLE_H__
0009 #define GOOGLE_PROTOBUF_VARINT_SHUFFLE_H__
0010
0011 #include <cassert>
0012 #include <cstddef>
0013 #include <cstdint>
0014 #include <type_traits>
0015 #include <utility>
0016
0017
0018 #include "google/protobuf/port_def.inc"
0019
0020 namespace google {
0021 namespace protobuf {
0022 namespace internal {
0023
0024
0025 template <int n>
0026 inline PROTOBUF_ALWAYS_INLINE int64_t VarintShlByte(int8_t byte, int64_t ones) {
0027 return static_cast<int64_t>((static_cast<uint64_t>(byte) << n * 7) |
0028 (static_cast<uint64_t>(ones) >> (64 - n * 7)));
0029 }
0030
0031
0032
0033
0034 template <int n>
0035 inline PROTOBUF_ALWAYS_INLINE bool VarintShlAnd(int8_t byte, int64_t ones,
0036 int64_t& res) {
0037 res &= VarintShlByte<n>(byte, ones);
0038 return res >= 0;
0039 }
0040
0041
0042
0043
0044 template <int n>
0045 inline PROTOBUF_ALWAYS_INLINE bool VarintShl(int8_t byte, int64_t ones,
0046 int64_t& res) {
0047 res = VarintShlByte<n>(byte, ones);
0048 return res >= 0;
0049 }
0050
0051 template <typename VarintType, int limit = 10>
0052 inline PROTOBUF_ALWAYS_INLINE const char* ShiftMixParseVarint(const char* p,
0053 int64_t& res1) {
0054 using Signed = std::make_signed_t<VarintType>;
0055 constexpr bool kIs64BitVarint = std::is_same<Signed, int64_t>::value;
0056 constexpr bool kIs32BitVarint = std::is_same<Signed, int32_t>::value;
0057 static_assert(kIs64BitVarint || kIs32BitVarint, "");
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 const auto next = [&p] { return static_cast<const int8_t>(*p++); };
0078 const auto last = [&p] { return static_cast<const int8_t>(p[-1]); };
0079
0080 int64_t res2, res3;
0081 res1 = next();
0082 if (PROTOBUF_PREDICT_TRUE(res1 >= 0)) return p;
0083 if (limit <= 1) goto limit0;
0084
0085
0086
0087 if (PROTOBUF_PREDICT_FALSE(VarintShl<1>(next(), res1, res2))) goto done1;
0088 if (limit <= 2) goto limit1;
0089 if (PROTOBUF_PREDICT_FALSE(VarintShl<2>(next(), res1, res3))) goto done2;
0090 if (limit <= 3) goto limit2;
0091 if (PROTOBUF_PREDICT_FALSE(VarintShlAnd<3>(next(), res1, res2))) goto done2;
0092 if (limit <= 4) goto limit2;
0093 if (PROTOBUF_PREDICT_TRUE(VarintShlAnd<4>(next(), res1, res3))) goto done2;
0094 if (limit <= 5) goto limit2;
0095
0096 if (kIs64BitVarint) {
0097 if (PROTOBUF_PREDICT_FALSE(VarintShlAnd<5>(next(), res1, res2))) goto done2;
0098 if (limit <= 6) goto limit2;
0099 if (PROTOBUF_PREDICT_FALSE(VarintShlAnd<6>(next(), res1, res3))) goto done2;
0100 if (limit <= 7) goto limit2;
0101 if (PROTOBUF_PREDICT_FALSE(VarintShlAnd<7>(next(), res1, res2))) goto done2;
0102 if (limit <= 8) goto limit2;
0103 if (PROTOBUF_PREDICT_FALSE(VarintShlAnd<8>(next(), res1, res3))) goto done2;
0104 if (limit <= 9) goto limit2;
0105 } else {
0106
0107 if (PROTOBUF_PREDICT_FALSE(!(next() & 0x80))) goto done2;
0108 if (limit <= 6) goto limit2;
0109 if (PROTOBUF_PREDICT_FALSE(!(next() & 0x80))) goto done2;
0110 if (limit <= 7) goto limit2;
0111 if (PROTOBUF_PREDICT_FALSE(!(next() & 0x80))) goto done2;
0112 if (limit <= 8) goto limit2;
0113 if (PROTOBUF_PREDICT_FALSE(!(next() & 0x80))) goto done2;
0114 if (limit <= 9) goto limit2;
0115 }
0116
0117
0118
0119
0120 if (PROTOBUF_PREDICT_TRUE(next() == 1)) goto done2;
0121
0122 if (PROTOBUF_PREDICT_FALSE(last() & 0x80)) {
0123
0124 return nullptr;
0125 }
0126
0127
0128
0129
0130
0131 if (kIs64BitVarint && (last() & 1) == 0) {
0132 static constexpr int bits = 64 - 1;
0133 #if defined(__GCC_ASM_FLAG_OUTPUTS__) && defined(__x86_64__)
0134
0135 asm("btc %[bits], %[res3]" : [res3] "+r"(res3) : [bits] "i"(bits));
0136 #else
0137 res3 ^= int64_t{1} << bits;
0138 #endif
0139 }
0140
0141 done2:
0142 res2 &= res3;
0143 done1:
0144 res1 &= res2;
0145 PROTOBUF_ASSUME(p != nullptr);
0146 return p;
0147 limit2:
0148 res2 &= res3;
0149 limit1:
0150 res1 &= res2;
0151 limit0:
0152 PROTOBUF_ASSUME(p != nullptr);
0153 PROTOBUF_ASSUME(res1 < 0);
0154 return p;
0155 }
0156
0157 }
0158 }
0159 }
0160
0161 #include "google/protobuf/port_undef.inc"
0162
0163 #endif