| // Copyright 2008 Google Inc. |
| // Author: Lincoln Smith |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef OPEN_VCDIFF_VARINT_BIGENDIAN_H_ |
| #define OPEN_VCDIFF_VARINT_BIGENDIAN_H_ |
| |
| // Functions for manipulating variable-length integers as described in |
| // RFC 3284, section 2. (See http://www.ietf.org/rfc/rfc3284.txt) |
| // This is the same format used by the Sfio library |
| // and by the public-domain Sqlite package. |
| // |
| // The implementation found in this file contains buffer bounds checks |
| // (not available in sqlite) and its goal is to improve speed |
| // by using as few test-and-branch instructions as possible. |
| // |
| // The Sqlite format has the refinement that, if a 64-bit value is expected, |
| // the ninth byte of the varint does not have a continuation bit, but instead |
| // encodes 8 bits of information. This allows 64 bits to be encoded compactly |
| // in nine bytes. However, that refinement does not appear in the format |
| // description in RFC 3284, and so it is not used here. In any case, |
| // this header file deals only with *signed* integer types, and so a |
| // "64-bit" integer is allowed to have only 63 significant bits; an additional |
| // 64th bit would indicate a negative value and therefore an error. |
| // |
| |
| #include <config.h> |
| #include <stdint.h> // int32_t, int64_t |
| #include <string> |
| #include "vcdiff_defs.h" // RESULT_ERROR |
| |
| namespace open_vcdiff { |
| |
| class OutputStringInterface; |
| |
| // This helper class is needed in order to ensure that |
| // VarintBE<SignedIntegerType>::kMaxBytes is treated |
| // as a compile-time constant when it is used as the size |
| // of a static array. |
| template <typename SignedIntegerType> class VarintMaxBytes; |
| |
| // 31 bits of data / 7 bits per byte <= 5 bytes |
| template<> class VarintMaxBytes<int32_t> { |
| public: |
| static const int kMaxBytes = 5; |
| }; |
| |
| // 63 bits of data / 7 bits per byte == 9 bytes |
| template<> class VarintMaxBytes<int64_t> { |
| public: |
| static const int kMaxBytes = 9; |
| }; |
| |
| // Objects of type VarintBE should not be instantiated. The class is a |
| // container for big-endian constant values and functions used to parse |
| // and write a particular signed integer type. |
| // Example: to parse a 32-bit integer value stored as a big-endian varint, use |
| // int32_t value = VarintBE<int32_t>::Parse(&ptr, limit); |
| // Only 32-bit and 64-bit signed integers (int32_t and int64_t) are supported. |
| // Using a different type as the template argument will likely result |
| // in a link-time error for an undefined Parse() or Append() function. |
| // |
| template <typename SignedIntegerType> |
| class VarintBE { // BE stands for Big-Endian |
| public: |
| typedef std::string string; |
| |
| // The maximum positive value represented by a SignedIntegerType. |
| static const SignedIntegerType kMaxVal; |
| |
| // Returns the maximum number of bytes needed to store a varint |
| // representation of a <SignedIntegerType> value. |
| static const int kMaxBytes = VarintMaxBytes<SignedIntegerType>::kMaxBytes; |
| |
| // Attempts to parse a big-endian varint from a prefix of the bytes |
| // in [ptr,limit-1] and convert it into a signed, non-negative 32-bit |
| // integer. Never reads a character at or beyond limit. |
| // If a parsed varint would exceed the maximum value of |
| // a <SignedIntegerType>, returns RESULT_ERROR and does not modify *ptr. |
| // If parsing a varint at *ptr (without exceeding the capacity of |
| // a <SignedIntegerType>) would require reading past limit, |
| // returns RESULT_END_OF_DATA and does not modify *ptr. |
| // If limit == NULL, returns RESULT_ERROR. |
| // If limit < *ptr, returns RESULT_END_OF_DATA. |
| static SignedIntegerType Parse(const char* limit, const char** ptr); |
| |
| // Returns the encoding length of the specified value. |
| static int Length(SignedIntegerType v); |
| |
| // Encodes "v" into "ptr" (which points to a buffer of length sufficient |
| // to hold "v")and returns the length of the encoding. |
| // The value of v must not be negative. |
| static int Encode(SignedIntegerType v, char* ptr); |
| |
| // Appends the varint representation of "value" to "*s". |
| // The value of v must not be negative. |
| static void AppendToString(SignedIntegerType value, string* s); |
| |
| // Appends the varint representation of "value" to output_string. |
| // The value of v must not be negative. |
| static void AppendToOutputString(SignedIntegerType value, |
| OutputStringInterface* output_string); |
| |
| private: |
| // Encodes "v" into the LAST few bytes of varint_buf (which is a char array |
| // of size kMaxBytes) and returns the length of the encoding. |
| // The result will be stored in buf[(kMaxBytes - length) : (kMaxBytes - 1)], |
| // rather than in buf[0 : length]. |
| // The value of v must not be negative. |
| static int EncodeInternal(SignedIntegerType v, char* varint_buf); |
| |
| // These are private to avoid constructing any objects of this type |
| VarintBE(); |
| VarintBE(const VarintBE&); // NOLINT |
| void operator=(const VarintBE&); |
| }; |
| |
| } // namespace open_vcdiff |
| |
| #endif // OPEN_VCDIFF_VARINT_BIGENDIAN_H_ |