public void Set(byte b) { if (_current == null || _current.Type != GapBlockType.ByteFill || _current.Byte != b) { _blocks.Add(_current = new GapBlock() { Type = GapBlockType.ByteFill, Count = 1, Byte = b }); } else { _current.Count++; } this.Length += BlockSize; }
private void set(GapBlockType type) { if (_current == null || _current.Type != type) { _blocks.Add(_current = new GapBlock() { Type = type, Count = 1 }); } else { _current.Count++; } this.Length += BlockSize; }
private long write(Stream s, bool writeHeader) { if (_gapLength % 4 != 0) //right most 2 bits will be 00 { throw new Exception("GapLength should be on a 4 byte boundary"); } long written = 0; MemorySection m = new MemorySection(new byte[0x10]); //for junk files % 4 (0 to 3) - load the 4 bytes, in a real iso the last byte would always be null (if not a legit junk file) //if a removed juk file the last byte will end with 2 bits (GapType.JunkFile) the rest of the 4 bytes is the file size / 4 //multiply value by 4 and add the fst file size. if (writeHeader) { if (JunkFile != 0) { m.WriteUInt32B(0, (uint)(JunkFileNulls << 2) | (uint)GapType.JunkFile); //junk file nulls (first 3 bytes are unused) m.WriteUInt32B(4, JunkFile); //length of file s.Write(m.Data, 0, 8); written += 8; } } else if (_blocks.Count == 0) { return(0); } if (_blocks.Count == 0) //non if padding for 32k alignment, or junk file with no padding { Set(); //add a junk item, length will be 0 } GapType gt; if (_blocks.Count == 1 && _blocks[0].Type == GapBlockType.Junk) { gt = GapType.AllJunk; } else if (_blocks.Count == 1 && _blocks[0].Type == GapBlockType.ByteFill && _blocks[0].Byte == 0) //00 scrubbed { gt = GapType.AllScrubbed; } else { gt = GapType.Mixed; } if (writeHeader) { long hdr = _gapLength >= 0xFFFFFFFCL ? 0xFFFFFFFCL : (uint)_gapLength; //always use 4 bytes if the gap is <= 0xFFFFFFFF - it should never be larger than that anyway. if so then use another 4 bytes hdr |= (uint)gt; m.WriteUInt32B(0, (uint)hdr); s.Write(m.Data, 0, 4); written += 4; if (hdr >= 0xFFFFFFFCL && _gapLength >= 0xFFFFFFFC) { m.WriteUInt32B(0, (uint)(_gapLength - 0xFFFFFFFCL)); //will cater for dual layer where most or all of it is empty s.Write(m.Data, 0, 4); written += 4; } } if (gt == GapType.Mixed || !writeHeader) //mixed { foreach (GapBlock b in _blocks) { if (b.NonJunk != null) { b.NonJunk.Position = 0; } uint cnt = (uint)b.Count; //total amount of blocks uint max; uint v = 0; uint w = 0; GapBlockType t = b.Type; while (cnt != 0) { if (t == GapBlockType.Junk || t == GapBlockType.NonJunk || t == GapBlockType.Repeat) { max = 0x3FFFFFFF; if (cnt > max) { v = max; } else { v = cnt; } cnt -= v; w = (uint)t << 30 | v; //type | count of 256 byte blocks } else if (t == GapBlockType.ByteFill) { max = 0x3FFFFF; if (cnt > max) { v = max; } else { v = cnt; } cnt -= v; w = (uint)t << 30 | v << 8 | b.Byte; //type | count of 256 byte blocks | fill byte } m.WriteUInt32B(0, w); s.Write(m.Data, 0, 4); //write encoded bytes written += 4; if (b.Type == GapBlockType.NonJunk) { written += b.NonJunk.Copy(s, Math.Min(b.NonJunk.Length - b.NonJunk.Position, v * Gap.BlockSize)); b.NonJunk.Close(); b.NonJunk = null; //free it } t = GapBlockType.Repeat; } } } _blocks.Clear(); _current = null; return(written); }