diff options
Diffstat (limited to 'src/common/varint.h')
-rw-r--r-- | src/common/varint.h | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/common/varint.h b/src/common/varint.h new file mode 100644 index 000000000..e62470fdf --- /dev/null +++ b/src/common/varint.h @@ -0,0 +1,62 @@ +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once + +#include <limits> +#include <type_traits> +#include <utility> +#include <sstream> +#include <string> + +namespace tools { + + template<typename OutputIt, typename T> + typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, void>::type + write_varint(OutputIt &&dest, T i) { + while (i >= 0x80) { + *dest++ = (static_cast<char>(i) & 0x7f) | 0x80; + i >>= 7; + } + *dest++ = static_cast<char>(i); + } + + template<typename t_type> + std::string get_varint_data(const t_type& v) + { + std::stringstream ss; + write_varint(std::ostreambuf_iterator<char>(ss), v); + return ss.str(); + } + + template<int bits, typename InputIt, typename T> + typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value && 0 <= bits && bits <= std::numeric_limits<T>::digits, int>::type + read_varint(InputIt &&first, InputIt &&last, T &i) { + int read = 0; + i = 0; + for (int shift = 0;; shift += 7) { + if (first == last) { + return read; // End of input. + } + unsigned char byte = *first++; + ++read; + if (shift + 7 >= bits && byte >= 1 << (bits - shift)) { + return -1; // Overflow. + } + if (byte == 0 && shift != 0) { + return -2; // Non-canonical representation. + } + i |= static_cast<T>(byte & 0x7f) << shift; + if ((byte & 0x80) == 0) { + break; + } + } + return read; + } + + template<typename InputIt, typename T> + int read_varint(InputIt &&first, InputIt &&last, T &i) { + return read_varint<std::numeric_limits<T>::digits, InputIt, T>(std::move(first), std::move(last), i); + } +} |