/// <summary> /// Reads a byte-sequence from the stream, appending them to an existing byte-sequence (which can be null); supported wire-types: String /// </summary> public static byte[] AppendBytes(byte[] value, ProtoReader reader) { switch (reader.wireType) { case WireType.String: int len = (int)reader.ReadUInt32Variant(false); reader.wireType = WireType.None; if (len == 0) { return(value); } int offset; if (value == null || value.Length == 0) { offset = 0; value = new byte[len]; } else { offset = value.Length; byte[] tmp = new byte[value.Length + len]; Helpers.BlockCopy(value, 0, tmp, 0, value.Length); value = tmp; } // value is now sized with the final length, and (if necessary) // contains the old data up to "offset" reader.position += len; // assume success while (len > reader.available) { if (reader.available > 0) { // copy what we *do* have Helpers.BlockCopy(reader.ioBuffer, reader.ioIndex, value, offset, reader.available); len -= reader.available; offset += reader.available; reader.ioIndex = reader.available = 0; // we've drained the buffer } // now refill the buffer (without overflowing it) int count = len > reader.ioBuffer.Length ? reader.ioBuffer.Length : len; if (count > 0) { reader.Ensure(count, true); } } // at this point, we know that len <= available if (len > 0) { // still need data, but we have enough buffered Helpers.BlockCopy(reader.ioBuffer, reader.ioIndex, value, offset, len); reader.ioIndex += len; reader.available -= len; } return(value); default: throw reader.CreateException(); } }
/// <summary> /// Makes the end of consuming a nested message in the stream; the stream must be either at the correct EndGroup /// marker, or all fields of the sub-message must have been consumed (in either case, this means ReadFieldHeader /// should return zero) /// </summary> public static void EndSubItem(SubItemToken token, ProtoReader reader) { int value = token.value; switch (reader.wireType) { case WireType.EndGroup: if (value >= 0) { throw AddErrorData(new ArgumentException("token"), reader); } if (-value != reader.fieldNumber) { throw reader.CreateException(); // wrong group ended! } reader.wireType = WireType.None; // this releases ReadFieldHeader reader.depth--; break; // case WireType.None: // TODO reinstate once reads reset the wire-type default: if (value < reader.position) { throw reader.CreateException(); } if (reader.blockEnd != reader.position && reader.blockEnd != int.MaxValue) { throw reader.CreateException(); } reader.blockEnd = value; reader.depth--; break; /*default: * throw reader.BorkedIt(); */ } }
public static void EndSubItem(SubItemToken token, ProtoReader reader) { if (reader == null) { throw new ArgumentNullException("reader"); } int value = token.value; WireType wireType = reader.wireType; if (wireType != WireType.EndGroup) { if (value < reader.position) { throw reader.CreateException("Sub-message not read entirely"); } if (reader.blockEnd != reader.position && reader.blockEnd != 2147483647) { throw reader.CreateException("Sub-message not read correctly"); } reader.blockEnd = value; reader.depth--; } else { if (value >= 0) { throw ProtoReader.AddErrorData(new ArgumentException("token"), reader); } if (-value != reader.fieldNumber) { throw reader.CreateException("Wrong group was ended"); } reader.wireType = WireType.None; reader.depth--; } }
/// <summary> /// Begins consuming a nested message in the stream; supported wire-types: StartGroup, String /// </summary> /// <remarks>The token returned must be help and used when callining EndSubItem</remarks> public static SubItemToken StartSubItem(ProtoReader reader) { switch (reader.wireType) { case WireType.StartGroup: reader.wireType = WireType.None; // to prevent glitches from double-calling reader.depth++; return(new SubItemToken(-reader.fieldNumber)); case WireType.String: int len = (int)reader.ReadUInt32Variant(false); if (len < 0) { throw AddErrorData(new InvalidOperationException(), reader); } int lastEnd = reader.blockEnd; reader.blockEnd = reader.position + len; reader.depth++; return(new SubItemToken(lastEnd)); default: throw reader.CreateException(); // throws } }
/// <summary> /// Reads a byte-sequence from the stream, appending them to an existing byte-sequence (which can be null); supported wire-types: String /// </summary> public static byte[] AppendBytes(byte[] value, ProtoReader reader) { switch (reader.wireType) { case WireType.String: int len = (int)reader.ReadUInt32Variant(false); reader.wireType = WireType.None; if (len == 0) return value; int offset; if(value == null || value.Length == 0) { offset = 0; value = new byte[len]; } else { offset = value.Length; byte[] tmp = new byte[value.Length + len]; Helpers.BlockCopy(value, 0, tmp, 0, value.Length); value = tmp; } // value is now sized with the final length, and (if necessary) // contains the old data up to "offset" reader.position += len; // assume success while (len > reader.available) { if (reader.available > 0) { // copy what we *do* have Helpers.BlockCopy(reader.ioBuffer, reader.ioIndex, value, offset, reader.available); len -= reader.available; offset += reader.available; reader.ioIndex = reader.available = 0; // we've drained the buffer } // now refill the buffer (without overflowing it) int count = len > reader.ioBuffer.Length ? reader.ioBuffer.Length : len; if (count > 0) reader.Ensure(count, true); } // at this point, we know that len <= available if (len > 0) { // still need data, but we have enough buffered Helpers.BlockCopy(reader.ioBuffer, reader.ioIndex, value, offset, len); reader.ioIndex += len; reader.available -= len; } return value; default: throw reader.CreateException(); } }
/// <summary> /// Begins consuming a nested message in the stream; supported wire-types: StartGroup, String /// </summary> /// <remarks>The token returned must be help and used when callining EndSubItem</remarks> public static SubItemToken StartSubItem(ProtoReader reader) { switch (reader.wireType) { case WireType.StartGroup: reader.wireType = WireType.None; // to prevent glitches from double-calling reader.depth++; return new SubItemToken(-reader.fieldNumber); case WireType.String: int len = (int)reader.ReadUInt32Variant(false); if (len < 0) throw AddErrorData(new InvalidOperationException(), reader); int lastEnd = reader.blockEnd; reader.blockEnd = reader.position + len; reader.depth++; return new SubItemToken(lastEnd); default: throw reader.CreateException(); // throws } }
/// <summary> /// Makes the end of consuming a nested message in the stream; the stream must be either at the correct EndGroup /// marker, or all fields of the sub-message must have been consumed (in either case, this means ReadFieldHeader /// should return zero) /// </summary> public static void EndSubItem(SubItemToken token, ProtoReader reader) { int value = token.value; switch (reader.wireType) { case WireType.EndGroup: if (value >= 0) throw AddErrorData(new ArgumentException("token"), reader); if (-value != reader.fieldNumber) throw reader.CreateException(); // wrong group ended! reader.wireType = WireType.None; // this releases ReadFieldHeader reader.depth--; break; // case WireType.None: // TODO reinstate once reads reset the wire-type default: if (value < reader.position) throw reader.CreateException(); if (reader.blockEnd != reader.position && reader.blockEnd != int.MaxValue) throw reader.CreateException(); reader.blockEnd = value; reader.depth--; break; /*default: throw reader.BorkedIt(); */ } }