~ubuntu-branches/ubuntu/oneiric/protobuf/oneiric

« back to all changes in this revision

Viewing changes to src/google/protobuf/io/coded_stream.cc

  • Committer: Bazaar Package Importer
  • Author(s): Iustin Pop
  • Date: 2008-08-03 11:01:44 UTC
  • Revision ID: james.westby@ubuntu.com-20080803110144-uyiw41bf1m2oe17t
Tags: upstream-2.0.0~b
ImportĀ upstreamĀ versionĀ 2.0.0~b

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Protocol Buffers - Google's data interchange format
 
2
// Copyright 2008 Google Inc.
 
3
// http://code.google.com/p/protobuf/
 
4
//
 
5
// Licensed under the Apache License, Version 2.0 (the "License");
 
6
// you may not use this file except in compliance with the License.
 
7
// You may obtain a copy of the License at
 
8
//
 
9
//      http://www.apache.org/licenses/LICENSE-2.0
 
10
//
 
11
// Unless required by applicable law or agreed to in writing, software
 
12
// distributed under the License is distributed on an "AS IS" BASIS,
 
13
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
14
// See the License for the specific language governing permissions and
 
15
// limitations under the License.
 
16
 
 
17
// Author: kenton@google.com (Kenton Varda)
 
18
//  Based on original Protocol Buffers design by
 
19
//  Sanjay Ghemawat, Jeff Dean, and others.
 
20
//
 
21
// This implementation is heavily optimized to make reads and writes
 
22
// of small values (especially varints) as fast as possible.  In
 
23
// particular, we optimize for the common case that a read or a write
 
24
// will not cross the end of the buffer, since we can avoid a lot
 
25
// of branching in this case.
 
26
 
 
27
#include <stack>
 
28
#include <limits.h>
 
29
#include <google/protobuf/io/coded_stream.h>
 
30
#include <google/protobuf/io/zero_copy_stream.h>
 
31
#include <google/protobuf/stubs/common.h>
 
32
#include <google/protobuf/stubs/stl_util-inl.h>
 
33
 
 
34
 
 
35
namespace google {
 
36
namespace protobuf {
 
37
namespace io {
 
38
 
 
39
namespace {
 
40
 
 
41
static const int kDefaultTotalBytesLimit = 64 << 20;  // 64MB
 
42
 
 
43
static const int kDefaultTotalBytesWarningThreshold = 32 << 20;  // 32MB
 
44
static const int kDefaultRecursionLimit = 64;
 
45
 
 
46
static const int kMaxVarintBytes = 10;
 
47
static const int kMaxVarint32Bytes = 5;
 
48
 
 
49
 
 
50
}  // namespace
 
51
 
 
52
// CodedInputStream ==================================================
 
53
 
 
54
CodedInputStream::CodedInputStream(ZeroCopyInputStream* input)
 
55
  : input_(input),
 
56
    buffer_(NULL),
 
57
    buffer_size_(0),
 
58
    total_bytes_read_(0),
 
59
    overflow_bytes_(0),
 
60
 
 
61
    last_tag_(0),
 
62
    legitimate_message_end_(false),
 
63
 
 
64
    aliasing_enabled_(false),
 
65
 
 
66
    current_limit_(INT_MAX),
 
67
    buffer_size_after_limit_(0),
 
68
 
 
69
    total_bytes_limit_(kDefaultTotalBytesLimit),
 
70
    total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
 
71
 
 
72
    recursion_depth_(0),
 
73
    recursion_limit_(kDefaultRecursionLimit) {
 
74
}
 
75
 
 
76
CodedInputStream::~CodedInputStream() {
 
77
  int backup_bytes = buffer_size_ + buffer_size_after_limit_ + overflow_bytes_;
 
78
  if (backup_bytes > 0) {
 
79
    // We still have bytes left over from the last buffer.  Back up over
 
80
    // them.
 
81
    input_->BackUp(backup_bytes);
 
82
  }
 
83
}
 
84
 
 
85
 
 
86
inline void CodedInputStream::RecomputeBufferLimits() {
 
87
  buffer_size_ += buffer_size_after_limit_;
 
88
  int closest_limit = min(current_limit_, total_bytes_limit_);
 
89
  if (closest_limit < total_bytes_read_) {
 
90
    // The limit position is in the current buffer.  We must adjust
 
91
    // the buffer size accordingly.
 
92
    buffer_size_after_limit_ = total_bytes_read_ - closest_limit;
 
93
    buffer_size_ -= buffer_size_after_limit_;
 
94
  } else {
 
95
    buffer_size_after_limit_ = 0;
 
96
  }
 
97
}
 
98
 
 
99
CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
 
100
  // Current position relative to the beginning of the stream.
 
101
  int current_position = total_bytes_read_ -
 
102
      (buffer_size_ + buffer_size_after_limit_);
 
103
 
 
104
  Limit old_limit = current_limit_;
 
105
 
 
106
  // security: byte_limit is possibly evil, so check for negative values
 
107
  // and overflow.
 
108
  if (byte_limit >= 0 &&
 
109
      byte_limit <= INT_MAX - current_position) {
 
110
    current_limit_ = current_position + byte_limit;
 
111
  } else {
 
112
    // Negative or overflow.
 
113
    current_limit_ = INT_MAX;
 
114
  }
 
115
 
 
116
  // We need to enforce all limits, not just the new one, so if the previous
 
117
  // limit was before the new requested limit, we continue to enforce the
 
118
  // previous limit.
 
119
  current_limit_ = min(current_limit_, old_limit);
 
120
 
 
121
  RecomputeBufferLimits();
 
122
  return old_limit;
 
123
}
 
124
 
 
125
void CodedInputStream::PopLimit(Limit limit) {
 
126
  // The limit passed in is actually the *old* limit, which we returned from
 
127
  // PushLimit().
 
128
  current_limit_ = limit;
 
129
  RecomputeBufferLimits();
 
130
 
 
131
  // We may no longer be at a legitimate message end.  ReadTag() needs to be
 
132
  // called again to find out.
 
133
  legitimate_message_end_ = false;
 
134
}
 
135
 
 
136
int CodedInputStream::BytesUntilLimit() {
 
137
  if (current_limit_ == INT_MAX) return -1;
 
138
  int current_position = total_bytes_read_ -
 
139
      (buffer_size_ + buffer_size_after_limit_);
 
140
 
 
141
  return current_limit_ - current_position;
 
142
}
 
143
 
 
144
void CodedInputStream::SetTotalBytesLimit(
 
145
    int total_bytes_limit, int warning_threshold) {
 
146
  // Make sure the limit isn't already past, since this could confuse other
 
147
  // code.
 
148
  int current_position = total_bytes_read_ -
 
149
      (buffer_size_ + buffer_size_after_limit_);
 
150
  total_bytes_limit_ = max(current_position, total_bytes_limit);
 
151
  total_bytes_warning_threshold_ = warning_threshold;
 
152
  RecomputeBufferLimits();
 
153
}
 
154
 
 
155
void CodedInputStream::PrintTotalBytesLimitError() {
 
156
  GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too "
 
157
                "big (more than " << total_bytes_limit_
 
158
             << " bytes).  To increase the limit (or to disable these "
 
159
                "warnings), see CodedInputStream::SetTotalBytesLimit() "
 
160
                "in google/protobuf/io/coded_stream.h.";
 
161
}
 
162
 
 
163
bool CodedInputStream::Skip(int count) {
 
164
  if (count < 0) return false;  // security: count is often user-supplied
 
165
 
 
166
  if (count <= buffer_size_) {
 
167
    // Just skipping within the current buffer.  Easy.
 
168
    Advance(count);
 
169
    return true;
 
170
  }
 
171
 
 
172
  if (buffer_size_after_limit_ > 0) {
 
173
    // We hit a limit inside this buffer.  Advance to the limit and fail.
 
174
    Advance(buffer_size_);
 
175
    return false;
 
176
  }
 
177
 
 
178
  count -= buffer_size_;
 
179
  buffer_ = NULL;
 
180
  buffer_size_ = 0;
 
181
 
 
182
  // Make sure this skip doesn't try to skip past the current limit.
 
183
  int closest_limit = min(current_limit_, total_bytes_limit_);
 
184
  int bytes_until_limit = closest_limit - total_bytes_read_;
 
185
  if (bytes_until_limit < count) {
 
186
    // We hit the limit.  Skip up to it then fail.
 
187
    total_bytes_read_ = closest_limit;
 
188
    input_->Skip(bytes_until_limit);
 
189
    return false;
 
190
  }
 
191
 
 
192
  total_bytes_read_ += count;
 
193
  return input_->Skip(count);
 
194
}
 
195
 
 
196
bool CodedInputStream::ReadRaw(void* buffer, int size) {
 
197
  while (buffer_size_ < size) {
 
198
    // Reading past end of buffer.  Copy what we have, then refresh.
 
199
    memcpy(buffer, buffer_, buffer_size_);
 
200
    buffer = reinterpret_cast<uint8*>(buffer) + buffer_size_;
 
201
    size -= buffer_size_;
 
202
    if (!Refresh()) return false;
 
203
  }
 
204
 
 
205
  memcpy(buffer, buffer_, size);
 
206
  Advance(size);
 
207
 
 
208
  return true;
 
209
}
 
210
 
 
211
bool CodedInputStream::ReadString(string* buffer, int size) {
 
212
  if (size < 0) return false;  // security: size is often user-supplied
 
213
 
 
214
  if (!buffer->empty()) {
 
215
    buffer->clear();
 
216
  }
 
217
 
 
218
  if (size < buffer_size_) {
 
219
    STLStringResizeUninitialized(buffer, size);
 
220
    memcpy((uint8*)buffer->data(), buffer_, size);
 
221
    Advance(size);
 
222
    return true;
 
223
  }
 
224
 
 
225
  while (buffer_size_ < size) {
 
226
    // Some STL implementations "helpfully" crash on buffer->append(NULL, 0).
 
227
    if (buffer_size_ != 0) {
 
228
      // Note:  string1.append(string2) is O(string2.size()) (as opposed to
 
229
      //   O(string1.size() + string2.size()), which would be bad).
 
230
      buffer->append(reinterpret_cast<const char*>(buffer_), buffer_size_);
 
231
    }
 
232
    size -= buffer_size_;
 
233
    if (!Refresh()) return false;
 
234
  }
 
235
 
 
236
  buffer->append(reinterpret_cast<const char*>(buffer_), size);
 
237
  Advance(size);
 
238
 
 
239
  return true;
 
240
}
 
241
 
 
242
 
 
243
bool CodedInputStream::ReadLittleEndian32(uint32* value) {
 
244
  uint8 bytes[sizeof(*value)];
 
245
 
 
246
  const uint8* ptr;
 
247
  if (buffer_size_ >= sizeof(*value)) {
 
248
    // Fast path:  Enough bytes in the buffer to read directly.
 
249
    ptr = buffer_;
 
250
    Advance(sizeof(*value));
 
251
  } else {
 
252
    // Slow path:  Had to read past the end of the buffer.
 
253
    if (!ReadRaw(bytes, sizeof(*value))) return false;
 
254
    ptr = bytes;
 
255
  }
 
256
 
 
257
  *value = (static_cast<uint32>(ptr[0])      ) |
 
258
           (static_cast<uint32>(ptr[1]) <<  8) |
 
259
           (static_cast<uint32>(ptr[2]) << 16) |
 
260
           (static_cast<uint32>(ptr[3]) << 24);
 
261
  return true;
 
262
}
 
263
 
 
264
bool CodedInputStream::ReadLittleEndian64(uint64* value) {
 
265
  uint8 bytes[sizeof(*value)];
 
266
 
 
267
  const uint8* ptr;
 
268
  if (buffer_size_ >= sizeof(*value)) {
 
269
    // Fast path:  Enough bytes in the buffer to read directly.
 
270
    ptr = buffer_;
 
271
    Advance(sizeof(*value));
 
272
  } else {
 
273
    // Slow path:  Had to read past the end of the buffer.
 
274
    if (!ReadRaw(bytes, sizeof(*value))) return false;
 
275
    ptr = bytes;
 
276
  }
 
277
 
 
278
  uint32 part0 = (static_cast<uint32>(ptr[0])      ) |
 
279
                 (static_cast<uint32>(ptr[1]) <<  8) |
 
280
                 (static_cast<uint32>(ptr[2]) << 16) |
 
281
                 (static_cast<uint32>(ptr[3]) << 24);
 
282
  uint32 part1 = (static_cast<uint32>(ptr[4])      ) |
 
283
                 (static_cast<uint32>(ptr[5]) <<  8) |
 
284
                 (static_cast<uint32>(ptr[6]) << 16) |
 
285
                 (static_cast<uint32>(ptr[7]) << 24);
 
286
  *value = static_cast<uint64>(part0) |
 
287
          (static_cast<uint64>(part1) << 32);
 
288
  return true;
 
289
}
 
290
 
 
291
bool CodedInputStream::ReadVarint32Fallback(uint32* value) {
 
292
  if (buffer_size_ >= kMaxVarintBytes ||
 
293
      // Optimization:  If the varint ends at exactly the end of the buffer,
 
294
      // we can detect that and still use the fast path.
 
295
      (buffer_size_ != 0 && !(buffer_[buffer_size_-1] & 0x80))) {
 
296
    // Fast path:  We have enough bytes left in the buffer to guarantee that
 
297
    // this read won't cross the end, so we can skip the checks.
 
298
    const uint8* ptr = buffer_;
 
299
    uint32 b;
 
300
    uint32 result;
 
301
 
 
302
    b = *(ptr++); result  = (b & 0x7F)      ; if (!(b & 0x80)) goto done;
 
303
    b = *(ptr++); result |= (b & 0x7F) <<  7; if (!(b & 0x80)) goto done;
 
304
    b = *(ptr++); result |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
 
305
    b = *(ptr++); result |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
 
306
    b = *(ptr++); result |=  b         << 28; if (!(b & 0x80)) goto done;
 
307
 
 
308
    // If the input is larger than 32 bits, we still need to read it all
 
309
    // and discard the high-order bits.
 
310
    for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) {
 
311
      b = *(ptr++); if (!(b & 0x80)) goto done;
 
312
    }
 
313
 
 
314
    // We have overrun the maximum size of a varint (10 bytes).  Assume
 
315
    // the data is corrupt.
 
316
    return false;
 
317
 
 
318
   done:
 
319
    Advance(ptr - buffer_);
 
320
    *value = result;
 
321
    return true;
 
322
 
 
323
  } else {
 
324
    // Optimization:  If we're at a limit, detect that quickly.  (This is
 
325
    // common when reading tags.)
 
326
    while (buffer_size_ == 0) {
 
327
      // Detect cases where we definitely hit a byte limit without calling
 
328
      // Refresh().
 
329
      if (// If we hit a limit, buffer_size_after_limit_ will be non-zero.
 
330
          buffer_size_after_limit_ > 0 &&
 
331
          // Make sure that the limit we hit is not total_bytes_limit_, since
 
332
          // in that case we still need to call Refresh() so that it prints an
 
333
          // error.
 
334
          total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) {
 
335
        // We hit a byte limit.
 
336
        legitimate_message_end_ = true;
 
337
        return false;
 
338
      }
 
339
 
 
340
      // Call refresh.
 
341
      if (!Refresh()) {
 
342
        // Refresh failed.  Make sure that it failed due to EOF, not because
 
343
        // we hit total_bytes_limit_, which, unlike normal limits, is not a
 
344
        // valid place to end a message.
 
345
        int current_position = total_bytes_read_ - buffer_size_after_limit_;
 
346
        if (current_position >= total_bytes_limit_) {
 
347
          // Hit total_bytes_limit_.  But if we also hit the normal limit,
 
348
          // we're still OK.
 
349
          legitimate_message_end_ = current_limit_ == total_bytes_limit_;
 
350
        } else {
 
351
          legitimate_message_end_ = true;
 
352
        }
 
353
        return false;
 
354
      }
 
355
    }
 
356
 
 
357
    // Slow path:  Just do a 64-bit read.
 
358
    uint64 result;
 
359
    if (!ReadVarint64(&result)) return false;
 
360
    *value = (uint32)result;
 
361
    return true;
 
362
  }
 
363
}
 
364
 
 
365
bool CodedInputStream::ReadVarint64(uint64* value) {
 
366
  if (buffer_size_ >= kMaxVarintBytes ||
 
367
      // Optimization:  If the varint ends at exactly the end of the buffer,
 
368
      // we can detect that and still use the fast path.
 
369
      (buffer_size_ != 0 && !(buffer_[buffer_size_-1] & 0x80))) {
 
370
    // Fast path:  We have enough bytes left in the buffer to guarantee that
 
371
    // this read won't cross the end, so we can skip the checks.
 
372
 
 
373
    const uint8* ptr = buffer_;
 
374
    uint32 b;
 
375
 
 
376
    // Splitting into 32-bit pieces gives better performance on 32-bit
 
377
    // processors.
 
378
    uint32 part0 = 0, part1 = 0, part2 = 0;
 
379
 
 
380
    b = *(ptr++); part0  = (b & 0x7F)      ; if (!(b & 0x80)) goto done;
 
381
    b = *(ptr++); part0 |= (b & 0x7F) <<  7; if (!(b & 0x80)) goto done;
 
382
    b = *(ptr++); part0 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
 
383
    b = *(ptr++); part0 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
 
384
    b = *(ptr++); part1  = (b & 0x7F)      ; if (!(b & 0x80)) goto done;
 
385
    b = *(ptr++); part1 |= (b & 0x7F) <<  7; if (!(b & 0x80)) goto done;
 
386
    b = *(ptr++); part1 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
 
387
    b = *(ptr++); part1 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
 
388
    b = *(ptr++); part2  = (b & 0x7F)      ; if (!(b & 0x80)) goto done;
 
389
    b = *(ptr++); part2 |= (b & 0x7F) <<  7; if (!(b & 0x80)) goto done;
 
390
 
 
391
    // We have overrun the maximum size of a varint (10 bytes).  The data
 
392
    // must be corrupt.
 
393
    return false;
 
394
 
 
395
   done:
 
396
    Advance(ptr - buffer_);
 
397
    *value = (static_cast<uint64>(part0)      ) |
 
398
             (static_cast<uint64>(part1) << 28) |
 
399
             (static_cast<uint64>(part2) << 56);
 
400
    return true;
 
401
 
 
402
  } else {
 
403
    // Slow path:  This read might cross the end of the buffer, so we
 
404
    // need to check and refresh the buffer if and when it does.
 
405
 
 
406
    uint64 result = 0;
 
407
    int count = 0;
 
408
    uint32 b;
 
409
 
 
410
    do {
 
411
      if (count == kMaxVarintBytes) return false;
 
412
      while (buffer_size_ == 0) {
 
413
        if (!Refresh()) return false;
 
414
      }
 
415
      b = *buffer_;
 
416
      result |= static_cast<uint64>(b & 0x7F) << (7 * count);
 
417
      Advance(1);
 
418
      ++count;
 
419
    } while(b & 0x80);
 
420
 
 
421
    *value = result;
 
422
    return true;
 
423
  }
 
424
}
 
425
 
 
426
bool CodedInputStream::Refresh() {
 
427
  if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0) {
 
428
    // We've hit a limit.  Stop.
 
429
    buffer_ += buffer_size_;
 
430
    buffer_size_ = 0;
 
431
 
 
432
    int current_position = total_bytes_read_ - buffer_size_after_limit_;
 
433
 
 
434
    if (current_position >= total_bytes_limit_ &&
 
435
        total_bytes_limit_ != current_limit_) {
 
436
      // Hit total_bytes_limit_.
 
437
      PrintTotalBytesLimitError();
 
438
    }
 
439
 
 
440
    return false;
 
441
  }
 
442
 
 
443
  if (total_bytes_warning_threshold_ >= 0 &&
 
444
      total_bytes_read_ >= total_bytes_warning_threshold_) {
 
445
      GOOGLE_LOG(WARNING) << "Reading dangerously large protocol message.  If the "
 
446
                      "message turns out to be larger than "
 
447
                   << total_bytes_limit_ << " bytes, parsing will be halted "
 
448
                      "for security reasons.  To increase the limit (or to "
 
449
                      "disable these warnings), see "
 
450
                      "CodedInputStream::SetTotalBytesLimit() in "
 
451
                      "google/protobuf/io/coded_stream.h.";
 
452
 
 
453
    // Don't warn again for this stream.
 
454
    total_bytes_warning_threshold_ = -1;
 
455
  }
 
456
 
 
457
  const void* void_buffer;
 
458
  if (input_->Next(&void_buffer, &buffer_size_)) {
 
459
    buffer_ = reinterpret_cast<const uint8*>(void_buffer);
 
460
    GOOGLE_CHECK_GE(buffer_size_, 0);
 
461
 
 
462
    if (total_bytes_read_ <= INT_MAX - buffer_size_) {
 
463
      total_bytes_read_ += buffer_size_;
 
464
    } else {
 
465
      // Overflow.  Reset buffer_size_ to not include the bytes beyond INT_MAX.
 
466
      // We can't get that far anyway, because total_bytes_limit_ is guaranteed
 
467
      // to be less than it.  We need to keep track of the number of bytes
 
468
      // we discarded, though, so that we can call input_->BackUp() to back
 
469
      // up over them on destruction.
 
470
 
 
471
      // The following line is equivalent to:
 
472
      //   overflow_bytes_ = total_bytes_read_ + buffer_size_ - INT_MAX;
 
473
      // except that it avoids overflows.  Signed integer overflow has
 
474
      // undefined results according to the C standard.
 
475
      overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size_);
 
476
      buffer_size_ -= overflow_bytes_;
 
477
      total_bytes_read_ = INT_MAX;
 
478
    }
 
479
 
 
480
    RecomputeBufferLimits();
 
481
    return true;
 
482
  } else {
 
483
    buffer_ = NULL;
 
484
    buffer_size_ = 0;
 
485
    return false;
 
486
  }
 
487
}
 
488
 
 
489
// CodedOutputStream =================================================
 
490
 
 
491
CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output)
 
492
  : output_(output),
 
493
    buffer_(NULL),
 
494
    buffer_size_(0),
 
495
    total_bytes_(0) {
 
496
}
 
497
 
 
498
CodedOutputStream::~CodedOutputStream() {
 
499
  if (buffer_size_ > 0) {
 
500
    output_->BackUp(buffer_size_);
 
501
  }
 
502
}
 
503
 
 
504
bool CodedOutputStream::WriteRaw(const void* data, int size) {
 
505
  while (buffer_size_ < size) {
 
506
    memcpy(buffer_, data, buffer_size_);
 
507
    size -= buffer_size_;
 
508
    data = reinterpret_cast<const uint8*>(data) + buffer_size_;
 
509
    if (!Refresh()) return false;
 
510
  }
 
511
 
 
512
  memcpy(buffer_, data, size);
 
513
  Advance(size);
 
514
  return true;
 
515
}
 
516
 
 
517
 
 
518
bool CodedOutputStream::WriteLittleEndian32(uint32 value) {
 
519
  uint8 bytes[sizeof(value)];
 
520
 
 
521
  bool use_fast = buffer_size_ >= sizeof(value);
 
522
  uint8* ptr = use_fast ? buffer_ : bytes;
 
523
 
 
524
  ptr[0] = static_cast<uint8>(value      );
 
525
  ptr[1] = static_cast<uint8>(value >>  8);
 
526
  ptr[2] = static_cast<uint8>(value >> 16);
 
527
  ptr[3] = static_cast<uint8>(value >> 24);
 
528
 
 
529
  if (use_fast) {
 
530
    Advance(sizeof(value));
 
531
    return true;
 
532
  } else {
 
533
    return WriteRaw(bytes, sizeof(value));
 
534
  }
 
535
}
 
536
 
 
537
bool CodedOutputStream::WriteLittleEndian64(uint64 value) {
 
538
  uint8 bytes[sizeof(value)];
 
539
 
 
540
  uint32 part0 = static_cast<uint32>(value);
 
541
  uint32 part1 = static_cast<uint32>(value >> 32);
 
542
 
 
543
  bool use_fast = buffer_size_ >= sizeof(value);
 
544
  uint8* ptr = use_fast ? buffer_ : bytes;
 
545
 
 
546
  ptr[0] = static_cast<uint8>(part0      );
 
547
  ptr[1] = static_cast<uint8>(part0 >>  8);
 
548
  ptr[2] = static_cast<uint8>(part0 >> 16);
 
549
  ptr[3] = static_cast<uint8>(part0 >> 24);
 
550
  ptr[4] = static_cast<uint8>(part1      );
 
551
  ptr[5] = static_cast<uint8>(part1 >>  8);
 
552
  ptr[6] = static_cast<uint8>(part1 >> 16);
 
553
  ptr[7] = static_cast<uint8>(part1 >> 24);
 
554
 
 
555
  if (use_fast) {
 
556
    Advance(sizeof(value));
 
557
    return true;
 
558
  } else {
 
559
    return WriteRaw(bytes, sizeof(value));
 
560
  }
 
561
}
 
562
 
 
563
bool CodedOutputStream::WriteVarint32Fallback(uint32 value) {
 
564
  if (buffer_size_ >= kMaxVarint32Bytes) {
 
565
    // Fast path:  We have enough bytes left in the buffer to guarantee that
 
566
    // this write won't cross the end, so we can skip the checks.
 
567
    uint8* target = buffer_;
 
568
 
 
569
    target[0] = static_cast<uint8>(value | 0x80);
 
570
    if (value >= (1 << 7)) {
 
571
      target[1] = static_cast<uint8>((value >>  7) | 0x80);
 
572
      if (value >= (1 << 14)) {
 
573
        target[2] = static_cast<uint8>((value >> 14) | 0x80);
 
574
        if (value >= (1 << 21)) {
 
575
          target[3] = static_cast<uint8>((value >> 21) | 0x80);
 
576
          if (value >= (1 << 28)) {
 
577
            target[4] = static_cast<uint8>(value >> 28);
 
578
            Advance(5);
 
579
          } else {
 
580
            target[3] &= 0x7F;
 
581
            Advance(4);
 
582
          }
 
583
        } else {
 
584
          target[2] &= 0x7F;
 
585
          Advance(3);
 
586
        }
 
587
      } else {
 
588
        target[1] &= 0x7F;
 
589
        Advance(2);
 
590
      }
 
591
    } else {
 
592
      target[0] &= 0x7F;
 
593
      Advance(1);
 
594
    }
 
595
 
 
596
    return true;
 
597
  } else {
 
598
    // Slow path:  This write might cross the end of the buffer, so we
 
599
    // compose the bytes first then use WriteRaw().
 
600
    uint8 bytes[kMaxVarint32Bytes];
 
601
    int size = 0;
 
602
    while (value > 0x7F) {
 
603
      bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80;
 
604
      value >>= 7;
 
605
    }
 
606
    bytes[size++] = static_cast<uint8>(value) & 0x7F;
 
607
    return WriteRaw(bytes, size);
 
608
  }
 
609
}
 
610
 
 
611
bool CodedOutputStream::WriteVarint64(uint64 value) {
 
612
  if (buffer_size_ >= kMaxVarintBytes) {
 
613
    // Fast path:  We have enough bytes left in the buffer to guarantee that
 
614
    // this write won't cross the end, so we can skip the checks.
 
615
    uint8* target = buffer_;
 
616
 
 
617
    // Splitting into 32-bit pieces gives better performance on 32-bit
 
618
    // processors.
 
619
    uint32 part0 = static_cast<uint32>(value      );
 
620
    uint32 part1 = static_cast<uint32>(value >> 28);
 
621
    uint32 part2 = static_cast<uint32>(value >> 56);
 
622
 
 
623
    int size;
 
624
 
 
625
    // Here we can't really optimize for small numbers, since the value is
 
626
    // split into three parts.  Cheking for numbers < 128, for instance,
 
627
    // would require three comparisons, since you'd have to make sure part1
 
628
    // and part2 are zero.  However, if the caller is using 64-bit integers,
 
629
    // it is likely that they expect the numbers to often be very large, so
 
630
    // we probably don't want to optimize for small numbers anyway.  Thus,
 
631
    // we end up with a hardcoded binary search tree...
 
632
    if (part2 == 0) {
 
633
      if (part1 == 0) {
 
634
        if (part0 < (1 << 14)) {
 
635
          if (part0 < (1 << 7)) {
 
636
            size = 1; goto size1;
 
637
          } else {
 
638
            size = 2; goto size2;
 
639
          }
 
640
        } else {
 
641
          if (part0 < (1 << 21)) {
 
642
            size = 3; goto size3;
 
643
          } else {
 
644
            size = 4; goto size4;
 
645
          }
 
646
        }
 
647
      } else {
 
648
        if (part1 < (1 << 14)) {
 
649
          if (part1 < (1 << 7)) {
 
650
            size = 5; goto size5;
 
651
          } else {
 
652
            size = 6; goto size6;
 
653
          }
 
654
        } else {
 
655
          if (part1 < (1 << 21)) {
 
656
            size = 7; goto size7;
 
657
          } else {
 
658
            size = 8; goto size8;
 
659
          }
 
660
        }
 
661
      }
 
662
    } else {
 
663
      if (part2 < (1 << 7)) {
 
664
        size = 9; goto size9;
 
665
      } else {
 
666
        size = 10; goto size10;
 
667
      }
 
668
    }
 
669
 
 
670
    GOOGLE_LOG(FATAL) << "Can't get here.";
 
671
 
 
672
    size10: target[9] = static_cast<uint8>((part2 >>  7) | 0x80);
 
673
    size9 : target[8] = static_cast<uint8>((part2      ) | 0x80);
 
674
    size8 : target[7] = static_cast<uint8>((part1 >> 21) | 0x80);
 
675
    size7 : target[6] = static_cast<uint8>((part1 >> 14) | 0x80);
 
676
    size6 : target[5] = static_cast<uint8>((part1 >>  7) | 0x80);
 
677
    size5 : target[4] = static_cast<uint8>((part1      ) | 0x80);
 
678
    size4 : target[3] = static_cast<uint8>((part0 >> 21) | 0x80);
 
679
    size3 : target[2] = static_cast<uint8>((part0 >> 14) | 0x80);
 
680
    size2 : target[1] = static_cast<uint8>((part0 >>  7) | 0x80);
 
681
    size1 : target[0] = static_cast<uint8>((part0      ) | 0x80);
 
682
 
 
683
    target[size-1] &= 0x7F;
 
684
    Advance(size);
 
685
    return true;
 
686
  } else {
 
687
    // Slow path:  This write might cross the end of the buffer, so we
 
688
    // compose the bytes first then use WriteRaw().
 
689
    uint8 bytes[kMaxVarintBytes];
 
690
    int size = 0;
 
691
    while (value > 0x7F) {
 
692
      bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80;
 
693
      value >>= 7;
 
694
    }
 
695
    bytes[size++] = static_cast<uint8>(value) & 0x7F;
 
696
    return WriteRaw(bytes, size);
 
697
  }
 
698
}
 
699
 
 
700
bool CodedOutputStream::Refresh() {
 
701
  void* void_buffer;
 
702
  if (output_->Next(&void_buffer, &buffer_size_)) {
 
703
    buffer_ = reinterpret_cast<uint8*>(void_buffer);
 
704
    total_bytes_ += buffer_size_;
 
705
    return true;
 
706
  } else {
 
707
    buffer_ = NULL;
 
708
    buffer_size_ = 0;
 
709
    return false;
 
710
  }
 
711
}
 
712
 
 
713
int CodedOutputStream::VarintSize32Fallback(uint32 value) {
 
714
  if (value < (1 << 7)) {
 
715
    return 1;
 
716
  } else if (value < (1 << 14)) {
 
717
    return 2;
 
718
  } else if (value < (1 << 21)) {
 
719
    return 3;
 
720
  } else if (value < (1 << 28)) {
 
721
    return 4;
 
722
  } else {
 
723
    return 5;
 
724
  }
 
725
}
 
726
 
 
727
int CodedOutputStream::VarintSize64(uint64 value) {
 
728
  if (value < (1ull << 35)) {
 
729
    if (value < (1ull << 7)) {
 
730
      return 1;
 
731
    } else if (value < (1ull << 14)) {
 
732
      return 2;
 
733
    } else if (value < (1ull << 21)) {
 
734
      return 3;
 
735
    } else if (value < (1ull << 28)) {
 
736
      return 4;
 
737
    } else {
 
738
      return 5;
 
739
    }
 
740
  } else {
 
741
    if (value < (1ull << 42)) {
 
742
      return 6;
 
743
    } else if (value < (1ull << 49)) {
 
744
      return 7;
 
745
    } else if (value < (1ull << 56)) {
 
746
      return 8;
 
747
    } else if (value < (1ull << 63)) {
 
748
      return 9;
 
749
    } else {
 
750
      return 10;
 
751
    }
 
752
  }
 
753
}
 
754
 
 
755
}  // namespace io
 
756
}  // namespace protobuf
 
757
}  // namespace google