| 120 | // Check om_uint32 is what it's meant to be |
| 121 | STATIC_ASSERT_UNSIGNED_TYPE(om_uint32); |
| 122 | STATIC_ASSERT(sizeof(om_uint32) == 4); |
| 123 | |
| 124 | om_byte part; |
| 125 | om_uint32 result = 0; |
| 126 | if (src_end - *src >= 5 || (src_end - *src > 0 && !(src_end[-1] & 0x80))) { |
| 127 | // No need to check src_end again, can't run off end. |
| 128 | part = static_cast<om_byte>(**src); |
| 129 | result = (part & 0x7f); |
| 130 | if (part & 0x80) { |
| 131 | part = static_cast<om_byte>((*src)[1]); |
| 132 | result |= ((part & 0x7f) << 7); |
| 133 | if (part & 0x80) { |
| 134 | part = static_cast<om_byte>((*src)[2]); |
| 135 | result |= ((part & 0x7f) << 14); |
| 136 | if (part & 0x80) { |
| 137 | part = static_cast<om_byte>((*src)[3]); |
| 138 | result |= ((part & 0x7f) << 21); |
| 139 | if (part & 0x80) { |
| 140 | part = static_cast<om_byte>((*src)[4]); |
| 141 | if (part & 0xf0) { |
| 142 | *src += 5; |
| 143 | goto overflow; |
| 144 | } |
| 145 | result |= ((part & 0x0f) << 28); |
| 146 | *src += 5; |
| 147 | } else { |
| 148 | *src += 4; |
| 149 | } |
| 150 | } else { |
| 151 | *src += 3; |
| 152 | } |
| 153 | } else { |
| 154 | *src += 2; |
| 155 | } |
| 156 | } else { |
| 157 | (*src)++; |
| 158 | } |
| 159 | if (resultptr) *resultptr = result; |
| 160 | return true; |
| 161 | } else { |
| 162 | // Slow path - need to check end at each step. |
| 163 | // Should be rare for this to be called, though. |
| 164 | |
| 165 | unsigned int shift = 0; |
| 166 | |
| 167 | while (true) { |
| 168 | if ((*src) == src_end) { |
| 169 | *src = 0; |
| 170 | return false; |
| 171 | } |
| 172 | |
| 173 | part = static_cast<om_byte>(**src); |
| 174 | (*src)++; |
| 175 | |
| 176 | // if new byte might cause overflow, and it does |
| 177 | if (((shift > (sizeof(om_uint32) - 1) * 8 + 1) && |
| 178 | ((part & 0x7f) << (shift % 8)) >= 0x100) || |
| 179 | (shift >= sizeof(om_uint32) * 8)) { |
| 180 | // Overflowed - move to end of this integer |
| 181 | while (true) { |
| 182 | if ((part & 0x80) == 0) return false; |
| 183 | if ((*src) == src_end) { |
| 184 | *src = 0; |
| 185 | return false; |
| 186 | } |
| 187 | part = static_cast<om_byte>(**src); |
| 188 | (*src)++; |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | result += om_uint32(part & 0x7f) << shift; |
| 193 | shift += 7; |
| 194 | |
| 195 | if ((part & 0x80) == 0) { |
| 196 | if (resultptr) *resultptr = result; |
| 197 | return true; |
| 198 | } |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | overflow: |
| 203 | // Overflowed - move to end of this integer |
| 204 | while (true) { |
| 205 | if ((*src) == src_end) { |
| 206 | *src = 0; |
| 207 | return false; |
| 208 | } |
| 209 | part = static_cast<om_byte>(**src); |
| 210 | (*src)++; |
| 211 | if ((part & 0x80) == 0) return false; |
| 212 | } |
| 213 | } |
| 214 | |