public static byte[] RA_ApplyStream(long pos, long size, Stream origin, Stream delta) { uint origin_ofst = (uint)origin.Position; uint base_delta_ofst = (uint)delta.Position; uint limit, total = 0; uint lenSrc = (uint)origin.Length; uint lenDelta = (uint)delta.Length; Fossil.StreamReader zDelta = new Fossil.StreamReader(delta); limit = zDelta.GetInt(); if (zDelta.GetChar() != '\n') { throw new Exception("size integer not terminated by \'\\n\'"); } //Fossil.StreamWriter zOut = new Fossil.StreamWriter(); List <byte> zOut = new List <byte>(); while (zDelta.HaveBytes()) { uint cnt, ofst, real_ofst, delta_ofst; cnt = zDelta.GetInt(); switch (zDelta.GetChar()) { case '@': real_ofst = zDelta.GetInt(); ofst = real_ofst + origin_ofst; if (zDelta.HaveBytes() && zDelta.GetChar() != ',') { throw new Exception("copy command not terminated by \',\'"); } total += cnt; if (total > limit) { throw new Exception("copy exceeds output file size"); } if (ofst + cnt > lenSrc) { throw new Exception("copy extends past end of input"); } if ((pos <= real_ofst && real_ofst < pos + size) || pos <= +cnt && real_ofst < pos + cnt + size) { origin.Seek(Math.Max((int)ofst, (int)pos + origin_ofst), SeekOrigin.Begin); for (int i = Math.Max((int)real_ofst, (int)pos); i < Math.Min((int)(real_ofst + cnt), pos + size); i++) { zOut.Add((byte)origin.ReadByte()); } } break; case ':': total += cnt; if (total > limit) { throw new Exception("insert command gives an output larger than predicted"); } if (cnt > lenDelta) { throw new Exception("insert count exceeds size of delta"); } delta_ofst = (uint)zDelta.BaseStream.Position - base_delta_ofst; if ((pos <= delta_ofst && delta_ofst < pos + size) || pos <= +cnt && delta_ofst < pos + cnt + size) { zDelta.BaseStream.Seek(Math.Max((int)pos - delta_ofst, 0), SeekOrigin.Current); for (int i = Math.Max((int)delta_ofst, (int)pos); i < Math.Min((int)(delta_ofst + cnt), pos + size); i++) { zOut.Add((byte)origin.ReadByte()); } } //zOut.PutArray(zDelta.BaseStream, (int)zDelta.BaseStream.Position, (int)(zDelta.BaseStream.Position + cnt)); //zDelta.BaseStream.Position += cnt; break; case ';': /*byte[] output = zOut.ToArray(); * if (cnt != Checksum(output)) * throw new Exception("bad checksum"); * if (total != limit) * throw new Exception("generated size does not match predicted size");*/ return(zOut.ToArray()); default: throw new Exception("unknown delta operator"); } } throw new Exception("unterminated delta"); }
public static MemoryStream ApplyStream(Stream origin, Stream delta) { uint origin_ofst = (uint)origin.Position; uint limit, total = 0; uint lenSrc = (uint)origin.Length; uint lenDelta = (uint)delta.Length; Fossil.StreamReader zDelta = new Fossil.StreamReader(delta); limit = zDelta.GetInt(); if (zDelta.GetChar() != '\n') { throw new Exception("size integer not terminated by \'\\n\'"); } Fossil.StreamWriter zOut = new Fossil.StreamWriter(); while (zDelta.HaveBytes()) { uint cnt, ofst; cnt = zDelta.GetInt(); switch (zDelta.GetChar()) { case '@': ofst = zDelta.GetInt() + origin_ofst; if (zDelta.HaveBytes() && zDelta.GetChar() != ',') { throw new Exception("copy command not terminated by \',\'"); } total += cnt; if (total > limit) { throw new Exception("copy exceeds output file size"); } if (ofst + cnt > lenSrc) { throw new Exception("copy extends past end of input"); } zOut.PutArray(origin, (int)ofst, (int)(ofst + cnt)); break; case ':': total += cnt; if (total > limit) { throw new Exception("insert command gives an output larger than predicted"); } if (cnt > lenDelta) { throw new Exception("insert count exceeds size of delta"); } zOut.PutArray(zDelta.BaseStream, (int)zDelta.BaseStream.Position, (int)(zDelta.BaseStream.Position + cnt)); //zDelta.BaseStream.Position += cnt; break; case ';': byte[] output = zOut.ToArray(); if (cnt != Checksum(output)) { throw new Exception("bad checksum"); } if (total != limit) { throw new Exception("generated size does not match predicted size"); } return(zOut.BaseStream); default: throw new Exception("unknown delta operator"); } } throw new Exception("unterminated delta"); }