1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright 2008 Google Inc.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Author: Lincoln Smith
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Licensed under the Apache License, Version 2.0 (the "License");
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// you may not use this file except in compliance with the License.
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// You may obtain a copy of the License at
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//      http://www.apache.org/licenses/LICENSE-2.0
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Unless required by applicable law or agreed to in writing, software
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// distributed under the License is distributed on an "AS IS" BASIS,
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// See the License for the specific language governing permissions and
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// limitations under the License.
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <config.h>
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "varint_bigendian.h"
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdint.h>  // int32_t, int64_t
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string.h>  // memcpy
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string>
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "logging.h"
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "google/output_string.h"
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace open_vcdiff {
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<> const int32_t VarintBE<int32_t>::kMaxVal = 0x7FFFFFFF;
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<> const int64_t VarintBE<int64_t>::kMaxVal = 0x7FFFFFFFFFFFFFFFULL;
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Reads a variable-length integer from **varint_ptr
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and returns it in a fixed-length representation.  Increments
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// *varint_ptr by the number of bytes read.  Will not read
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// past limit.  Returns RESULT_ERROR if the value parsed
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// does not fit in a non-negative signed integer, or if limit is NULL.
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns RESULT_END_OF_DATA if address_stream_end is reached
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// before the whole integer can be decoded.
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <typename SignedIntegerType>
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSignedIntegerType VarintBE<SignedIntegerType>::Parse(const char* limit,
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                     const char** varint_ptr) {
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!limit) {
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return RESULT_ERROR;
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SignedIntegerType result = 0;
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (const char* parse_ptr = *varint_ptr; parse_ptr < limit; ++parse_ptr) {
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result += *parse_ptr & 0x7F;
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!(*parse_ptr & 0x80)) {
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      *varint_ptr = parse_ptr + 1;
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return result;
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (result > (kMaxVal >> 7)) {
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Shifting result by 7 bits would produce a number too large
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // to be stored in a non-negative SignedIntegerType (an overflow.)
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return RESULT_ERROR;
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = result << 7;
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return RESULT_END_OF_DATA;
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <typename SignedIntegerType>
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint VarintBE<SignedIntegerType>::EncodeInternal(SignedIntegerType v,
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                char* varint_buf) {
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (v < 0) {
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(DFATAL) << "Negative value " << v
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                << " passed to VarintBE::EncodeInternal,"
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                   " which requires non-negative argument" << LOG_ENDL;
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return 0;
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int length = 1;
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char* buf_ptr = &varint_buf[kMaxBytes - 1];
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *buf_ptr = static_cast<char>(v & 0x7F);
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  --buf_ptr;
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  v >>= 7;
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while (v) {
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *buf_ptr = static_cast<char>((v & 0x7F) | 0x80);  // add continuation bit
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    --buf_ptr;
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ++length;
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    v >>= 7;
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return length;
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <typename SignedIntegerType>
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint VarintBE<SignedIntegerType>::Encode(SignedIntegerType v, char* ptr) {
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char varint_buf[kMaxBytes];
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int length = EncodeInternal(v, varint_buf);
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memcpy(ptr, &varint_buf[kMaxBytes - length], length);
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return length;
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <typename SignedIntegerType>
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid VarintBE<SignedIntegerType>::AppendToString(SignedIntegerType value,
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                 string* s) {
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char varint_buf[kMaxBytes];
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int length = EncodeInternal(value, varint_buf);
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  s->append(&varint_buf[kMaxBytes - length], length);
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <typename SignedIntegerType>
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid VarintBE<SignedIntegerType>::AppendToOutputString(
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SignedIntegerType value,
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    OutputStringInterface* output_string) {
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char varint_buf[kMaxBytes];
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int length = EncodeInternal(value, varint_buf);
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  output_string->append(&varint_buf[kMaxBytes - length], length);
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns the encoding length of the specified value.
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <typename SignedIntegerType>
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint VarintBE<SignedIntegerType>::Length(SignedIntegerType v) {
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (v < 0) {
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(DFATAL) << "Negative value " << v
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                << " passed to VarintBE::Length,"
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                   " which requires non-negative argument" << LOG_ENDL;
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return 0;
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int length = 0;
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  do {
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    v >>= 7;
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ++length;
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while (v);
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return length;
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate class VarintBE<int32_t>;
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate class VarintBE<int64_t>;
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace open_vcdiff
129