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 |
10 | unsigned char Encoder::kEmptyBuffer = 0; |
11 | |
12 | Encoder::Encoder() |
13 | : orig_(NULL), |
14 | buf_(NULL), |
15 | limit_(NULL), |
16 | underlying_buffer_(&kEmptyBuffer) { |
17 | } |
18 | |
19 | Encoder::~Encoder() { |
20 | if (underlying_buffer_ != &kEmptyBuffer) { |
21 | delete[] underlying_buffer_; |
22 | } |
23 | } |
24 | |
25 | int Encoder::varint32_length(uint32 v) { |
26 | return Varint::Length32(v); |
27 | } |
28 | |
29 | int Encoder::varint64_length(uint64 v) { |
30 | return Varint::Length64(v); |
31 | } |
32 | |
33 | void 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 | |
55 | void Encoder::RemoveLast(int N) { |
56 | CHECK(length() >= N); |
57 | buf_ -= N; |
58 | } |
59 | |
60 | void 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 |
67 | bool 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 |
77 | bool 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 | |