// 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 #include // int32_t, int64_t #include #include "vcdiff_defs.h" // RESULT_ERROR namespace open_vcdiff { class OutputStringInterface; // This helper class is needed in order to ensure that // VarintBE::kMaxBytes is treated // as a compile-time constant when it is used as the size // of a static array. template class VarintMaxBytes; // 31 bits of data / 7 bits per byte <= 5 bytes template<> class VarintMaxBytes { public: static const int kMaxBytes = 5; }; // 63 bits of data / 7 bits per byte == 9 bytes template<> class VarintMaxBytes { 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::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 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 value. static const int kMaxBytes = VarintMaxBytes::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 , returns RESULT_ERROR and does not modify *ptr. // If parsing a varint at *ptr (without exceeding the capacity of // a ) 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_