X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FVarint.h;h=e162671815a7fbb357f65a5e2ef368a7a269b364;hb=59527d6ae3453d12190f38762637c0fd19b6abd7;hp=4ad1cc778a4cd3abd3f34a517ec7544ecc6ed2db;hpb=22afce906d7e98d95f8c45c3301072d9fd891d41;p=folly.git diff --git a/folly/Varint.h b/folly/Varint.h index 4ad1cc77..e1626718 100644 --- a/folly/Varint.h +++ b/folly/Varint.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2015 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,9 @@ #ifndef FOLLY_VARINT_H_ #define FOLLY_VARINT_H_ -#include "folly/Range.h" +#include +#include +#include namespace folly { @@ -55,7 +57,8 @@ size_t encodeVarint(uint64_t val, uint8_t* buf); /** * Decode a value from a given buffer, advances data past the returned value. */ -uint64_t decodeVarint(ByteRange& data); +template +uint64_t decodeVarint(Range& data); /** * ZigZag encoding that maps signed integers with a small absolute value @@ -88,13 +91,20 @@ inline size_t encodeVarint(uint64_t val, uint8_t* buf) { return p - buf; } -inline uint64_t decodeVarint(ByteRange& data) { +template +inline uint64_t decodeVarint(Range& data) { + static_assert( + std::is_same::type, char>::value || + std::is_same::type, unsigned char>::value, + "Only character ranges are supported"); + const int8_t* begin = reinterpret_cast(data.begin()); const int8_t* end = reinterpret_cast(data.end()); const int8_t* p = begin; uint64_t val = 0; - if (LIKELY(end - begin >= kMaxVarintLength64)) { // fast path + // end is always greater than or equal to begin, so this subtraction is safe + if (LIKELY(size_t(end - begin) >= kMaxVarintLength64)) { // fast path int64_t b; do { b = *p++; val = (b & 0x7f) ; if (b >= 0) break; @@ -107,7 +117,7 @@ inline uint64_t decodeVarint(ByteRange& data) { b = *p++; val |= (b & 0x7f) << 49; if (b >= 0) break; b = *p++; val |= (b & 0x7f) << 56; if (b >= 0) break; b = *p++; val |= (b & 0x7f) << 63; if (b >= 0) break; - throw std::invalid_argument("Invalid varint value"); // too big + throw std::invalid_argument("Invalid varint value. Too big."); } while (false); } else { int shift = 0; @@ -115,7 +125,11 @@ inline uint64_t decodeVarint(ByteRange& data) { val |= static_cast(*p++ & 0x7f) << shift; shift += 7; } - if (p == end) throw std::invalid_argument("Invalid varint value"); + if (p == end) { + throw std::invalid_argument("Invalid varint value. Too small: " + + folly::to(end - begin) + + " bytes"); + } val |= static_cast(*p++) << shift; } @@ -126,4 +140,3 @@ inline uint64_t decodeVarint(ByteRange& data) { } // namespaces #endif /* FOLLY_VARINT_H_ */ -