1//
2// Copyright 2000 - 2003 Google Inc.
3//
4//
5
6#include "base/logging.h"
7#include "util/coding/coder.h"
8
9// An initialization value used when we are allowed to
10unsigned char Encoder::kEmptyBuffer = 0;
11
12Encoder::Encoder()
13 : orig_(NULL),
14 buf_(NULL),
15 limit_(NULL),
16 underlying_buffer_(&kEmptyBuffer) {
17}
18
19Encoder::~Encoder() {
20 if (underlying_buffer_ != &kEmptyBuffer) {
21 delete[] underlying_buffer_;
22 }
23}
24
25int Encoder::varint32_length(uint32 v) {
26 return Varint::Length32(v);
27}
28
29int Encoder::varint64_length(uint64 v) {
30 return Varint::Length64(v);
31}
32
33void Encoder::EnsureSlowPath(int N) {
34 CHECK(ensure_allowed());
35 assert(avail() < N);
36 assert(length() == 0 || orig_ == underlying_buffer_);
37
38 // Double buffer size, but make sure we always have at least N extra bytes
39 int current_len = length();
40 int new_capacity = max(current_len + N, 2 * current_len);
41
42 unsigned char* new_buffer = new unsigned char[new_capacity];
43 memcpy(new_buffer, underlying_buffer_, current_len);
44 if (underlying_buffer_ != &kEmptyBuffer) {
45 delete[] underlying_buffer_;
46 }
47 underlying_buffer_ = new_buffer;
48
49 orig_ = new_buffer;
50 limit_ = new_buffer + new_capacity;
51 buf_ = orig_ + current_len;
52 CHECK(avail() >= N);
53}
54
55void Encoder::RemoveLast(int N) {
56 CHECK(length() >= N);
57 buf_ -= N;
58}
59
60void Encoder::Resize(int N) {
61 CHECK(length() >= N);
62 buf_ = orig_ + N;
63 assert(length() == N);
64}
65
66// Special optimized version: does not use Varint
67bool Decoder::get_varint32(uint32* v) {
68 const char* r = Varint::Parse32WithLimit(
69 reinterpret_cast<const char*>(buf_),
70 reinterpret_cast<const char*>(limit_), v);
71 if (r == NULL) { return false; }
72 buf_ = reinterpret_cast<const unsigned char*>(r);
73 return true;
74}
75
76// Special optimized version: does not use Varint
77bool Decoder::get_varint64(uint64* v) {
78 uint64 result = 0;
79
80 if (buf_ + Varint::kMax64 <= limit_) {
81 const char* r = Varint::Parse64(reinterpret_cast<const char*>(buf_), v);
82 if (r == NULL) {
83 return false;
84 } else {
85 buf_ = reinterpret_cast<const unsigned char*>(r);
86 return true;
87 }
88 } else {
89 int shift = 0; // How much to shift next set of bits
90 unsigned char byte;
91 do {
92 if ((shift >= 64) || (buf_ >= limit_)) {
93 // Out of range
94 return false;
95 }
96
97 // Get 7 bits from next byte
98 byte = *(buf_++);
99 result |= static_cast<uint64>(byte & 127) << shift;
100 shift += 7;
101 } while ((byte & 128) != 0);
102 *v = result;
103 return true;
104 }
105}
106