• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2008 Google Inc.
2 // Author: Lincoln Smith
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #ifndef OPEN_VCDIFF_VARINT_BIGENDIAN_H_
17 #define OPEN_VCDIFF_VARINT_BIGENDIAN_H_
18 
19 // Functions for manipulating variable-length integers as described in
20 // RFC 3284, section 2.  (See http://www.ietf.org/rfc/rfc3284.txt)
21 // This is the same format used by the Sfio library
22 // and by the public-domain Sqlite package.
23 //
24 // The implementation found in this file contains buffer bounds checks
25 // (not available in sqlite) and its goal is to improve speed
26 // by using as few test-and-branch instructions as possible.
27 //
28 // The Sqlite format has the refinement that, if a 64-bit value is expected,
29 // the ninth byte of the varint does not have a continuation bit, but instead
30 // encodes 8 bits of information.  This allows 64 bits to be encoded compactly
31 // in nine bytes.  However, that refinement does not appear in the format
32 // description in RFC 3284, and so it is not used here.  In any case,
33 // this header file deals only with *signed* integer types, and so a
34 // "64-bit" integer is allowed to have only 63 significant bits; an additional
35 // 64th bit would indicate a negative value and therefore an error.
36 //
37 
38 #include <config.h>
39 #include <stdint.h>  // int32_t, int64_t
40 #include <string>
41 #include "vcdiff_defs.h"  // RESULT_ERROR
42 
43 namespace open_vcdiff {
44 
45 class OutputStringInterface;
46 
47 // This helper class is needed in order to ensure that
48 // VarintBE<SignedIntegerType>::kMaxBytes is treated
49 // as a compile-time constant when it is used as the size
50 // of a static array.
51 template <typename SignedIntegerType> class VarintMaxBytes;
52 
53 // 31 bits of data / 7 bits per byte <= 5 bytes
54 template<> class VarintMaxBytes<int32_t> {
55  public:
56   static const int kMaxBytes = 5;
57 };
58 
59 // 63 bits of data / 7 bits per byte == 9 bytes
60 template<> class VarintMaxBytes<int64_t> {
61  public:
62   static const int kMaxBytes = 9;
63 };
64 
65 // Objects of type VarintBE should not be instantiated.  The class is a
66 // container for big-endian constant values and functions used to parse
67 // and write a particular signed integer type.
68 // Example: to parse a 32-bit integer value stored as a big-endian varint, use
69 //     int32_t value = VarintBE<int32_t>::Parse(&ptr, limit);
70 // Only 32-bit and 64-bit signed integers (int32_t and int64_t) are supported.
71 // Using a different type as the template argument will likely result
72 // in a link-time error for an undefined Parse() or Append() function.
73 //
74 template <typename SignedIntegerType>
75 class VarintBE {  // BE stands for Big-Endian
76  public:
77   typedef std::string string;
78 
79   // The maximum positive value represented by a SignedIntegerType.
80   static const SignedIntegerType kMaxVal;
81 
82   // Returns the maximum number of bytes needed to store a varint
83   // representation of a <SignedIntegerType> value.
84   static const int kMaxBytes = VarintMaxBytes<SignedIntegerType>::kMaxBytes;
85 
86   // Attempts to parse a big-endian varint from a prefix of the bytes
87   // in [ptr,limit-1] and convert it into a signed, non-negative 32-bit
88   // integer.  Never reads a character at or beyond limit.
89   // If a parsed varint would exceed the maximum value of
90   // a <SignedIntegerType>, returns RESULT_ERROR and does not modify *ptr.
91   // If parsing a varint at *ptr (without exceeding the capacity of
92   // a <SignedIntegerType>) would require reading past limit,
93   // returns RESULT_END_OF_DATA and does not modify *ptr.
94   // If limit == NULL, returns RESULT_ERROR.
95   // If limit < *ptr, returns RESULT_END_OF_DATA.
96   static SignedIntegerType Parse(const char* limit, const char** ptr);
97 
98   // Returns the encoding length of the specified value.
99   static int Length(SignedIntegerType v);
100 
101   // Encodes "v" into "ptr" (which points to a buffer of length sufficient
102   // to hold "v")and returns the length of the encoding.
103   // The value of v must not be negative.
104   static int Encode(SignedIntegerType v, char* ptr);
105 
106   // Appends the varint representation of "value" to "*s".
107   // The value of v must not be negative.
108   static void AppendToString(SignedIntegerType value, string* s);
109 
110   // Appends the varint representation of "value" to output_string.
111   // The value of v must not be negative.
112   static void AppendToOutputString(SignedIntegerType value,
113                                    OutputStringInterface* output_string);
114 
115  private:
116   // Encodes "v" into the LAST few bytes of varint_buf (which is a char array
117   // of size kMaxBytes) and returns the length of the encoding.
118   // The result will be stored in buf[(kMaxBytes - length) : (kMaxBytes - 1)],
119   // rather than in buf[0 : length].
120   // The value of v must not be negative.
121   static int EncodeInternal(SignedIntegerType v, char* varint_buf);
122 
123   // These are private to avoid constructing any objects of this type
124   VarintBE();
125   VarintBE(const VarintBE&);  // NOLINT
126   void operator=(const VarintBE&);
127 };
128 
129 }  // namespace open_vcdiff
130 
131 #endif  // OPEN_VCDIFF_VARINT_BIGENDIAN_H_
132