aboutsummaryrefslogtreecommitdiff
path: root/csharp/ProtocolBuffers/CodedInputStream.cs
diff options
context:
space:
mode:
Diffstat (limited to 'csharp/ProtocolBuffers/CodedInputStream.cs')
-rw-r--r--csharp/ProtocolBuffers/CodedInputStream.cs59
1 files changed, 52 insertions, 7 deletions
diff --git a/csharp/ProtocolBuffers/CodedInputStream.cs b/csharp/ProtocolBuffers/CodedInputStream.cs
index fd6f1de7..30969820 100644
--- a/csharp/ProtocolBuffers/CodedInputStream.cs
+++ b/csharp/ProtocolBuffers/CodedInputStream.cs
@@ -356,14 +356,15 @@ namespace Google.ProtocolBuffers {
#endregion
#region Underlying reading primitives
+
/// <summary>
- /// Read a raw Varint from the stream. If larger than 32 bits, discard the upper bits.
+ /// Same code as ReadRawVarint32, but read each byte individually, checking for
+ /// buffer overflow.
/// </summary>
- /// <returns></returns>
- public uint ReadRawVarint32() {
+ private uint SlowReadRawVarint32() {
int tmp = ReadRawByte();
if (tmp < 128) {
- return (uint) tmp;
+ return (uint)tmp;
}
int result = tmp & 0x7f;
if ((tmp = ReadRawByte()) < 128) {
@@ -382,14 +383,59 @@ namespace Google.ProtocolBuffers {
if (tmp >= 128) {
// Discard upper 32 bits.
for (int i = 0; i < 5; i++) {
- if (ReadRawByte() < 128) return (uint) result;
+ if (ReadRawByte() < 128) return (uint)result;
+ }
+ throw InvalidProtocolBufferException.MalformedVarint();
+ }
+ }
+ }
+ }
+ return (uint)result;
+ }
+
+ /// <summary>
+ /// Read a raw Varint from the stream. If larger than 32 bits, discard the upper bits.
+ /// This method is optimised for the case where we've got lots of data in the buffer.
+ /// That means we can check the size just once, then just read directly from the buffer
+ /// without constant rechecking of the buffer length.
+ /// </summary>
+ public uint ReadRawVarint32() {
+ if (bufferPos + 5 > bufferSize) {
+ return SlowReadRawVarint32();
+ }
+
+ int tmp = buffer[bufferPos++];
+ if (tmp < 128) {
+ return (uint)tmp;
+ }
+ int result = tmp & 0x7f;
+ if ((tmp = buffer[bufferPos++]) < 128) {
+ result |= tmp << 7;
+ } else {
+ result |= (tmp & 0x7f) << 7;
+ if ((tmp = buffer[bufferPos++]) < 128) {
+ result |= tmp << 14;
+ } else {
+ result |= (tmp & 0x7f) << 14;
+ if ((tmp = buffer[bufferPos++]) < 128) {
+ result |= tmp << 21;
+ } else {
+ result |= (tmp & 0x7f) << 21;
+ result |= (tmp = buffer[bufferPos++]) << 28;
+ if (tmp >= 128) {
+ // Discard upper 32 bits.
+ // Note that this has to use ReadRawByte() as we only ensure we've
+ // got at least 5 bytes at the start of the method. This lets us
+ // use the fast path in more cases, and we rarely hit this section of code.
+ for (int i = 0; i < 5; i++) {
+ if (ReadRawByte() < 128) return (uint)result;
}
throw InvalidProtocolBufferException.MalformedVarint();
}
}
}
}
- return (uint) result;
+ return (uint)result;
}
/// <summary>
@@ -571,7 +617,6 @@ namespace Google.ProtocolBuffers {
bufferPos = 0;
bufferSize = (input == null) ? 0 : input.Read(buffer, 0, buffer.Length);
if (bufferSize == 0) {
- bufferSize = 0;
if (mustSucceed) {
throw InvalidProtocolBufferException.TruncatedMessage();
} else {