/// /// class SimFile /// Models the file format used with Record/Playback Simulator (Summer 2008) /// /// 16 Mar 2009 - D.Bozarth - Sonoma State Engineering Science /// #region Using directives using System; using System.Collections.Generic; using System.IO; using System.Text; using Utility; #endregion namespace SimFile { public class SimFile { #region Constants // public const string VERSION_ID = "SimFile1.0"; public const int BUF_SIZE_DFLT = Utility.StreamProcessor.BufSizeDflt; public enum SignalId { A, B, C, D, E, All = -1 }; public enum ComponentId { Real, Imag }; public enum ByteOffset { B0, B1, B2, B3, All= -1 }; public enum FileContent { All, FileHdr, SwpAll, SwpHdr, Data, SignalData, IntegerData }; public enum FileFormat { Binary, CsvByte, Csv, Xml }; // public const int nFlagsSimData = 4; public const int nInt16PerSample = 4; public const int nComponentsPerSignal = 2; public const int nSignalsPerSample = 5; public const int nComponentsPerSample = nComponentsPerSignal * nSignalsPerSample; public const int nBytesPerBool = sizeof( bool ); public const int nBytesPerInt16 = sizeof( Int16 ); public const int nBytesPerInt32 = sizeof( Int32 ); public const int nBytesPerSingle = sizeof( Single ); public const int nBytesPerComponent = nBytesPerSingle; public const int nBytesPerSignal = nBytesPerComponent * nComponentsPerSignal; public const int nBytesSignalPerSample = nBytesPerSignal * nSignalsPerSample; public const int nBytesInt16PerSample = nBytesPerInt16 * nInt16PerSample; public const int nBytesIntegerPerSample = nBytesInt16PerSample; public const int nBytesPerSample = nBytesSignalPerSample + nBytesIntegerPerSample; public const int nBytesExtraField = nFlagsSimData * nBytesPerBool + 3 * nBytesPerInt16; public const int nBytesPerMapEntry = 2 * nBytesPerInt32; // Note: Wherever the native implementation used size_t or long, // .. here we use int32. public const int nBytesSweepHdr = sizeof(int) + sizeof(int) + sizeof(int) + sizeof(int) + (sizeof(bool) * nFlagsSimData) + sizeof(short) + sizeof(short) + sizeof(short) + sizeof(int) + sizeof(int) ; public const int nBytesFileHdr = sizeof(int) + sizeof(int) + (sizeof(bool) * nFlagsSimData) + sizeof(short) + sizeof(short) + sizeof(short) + sizeof(int) + sizeof(int) ; // #endregion Constants #region Contained classes of class SimFile // public class Test { } public struct Sample { public Pair A; // 5 complex numbers {real, imag}. public Pair B; public Pair C; public Pair D; public Pair E; public short one; public short two; public short three; public short four; public override string ToString() { return "{" + A.First + ", " + A.Second + "} " + "{" + B.First + ", " + B.Second + "} " + "{" + C.First + ", " + C.Second + "} " + "{" + D.First + ", " + D.Second + "} " + "{" + E.First + ", " + E.Second + "} " + one + " " + two + " " + three + " " + four ; } } // struct Sample public class Sweep : List { #region Methods of class Sweep public Sweep() { sweepHdrExtra = new byte[nBytesExtraField]; SweepIds = new List(); Locas = new List(); fileName = ""; fileDesc = ""; } public Io.Result StreamWrite( Stream outStream, FileContent fc ) { return StreamWrite( outStream, fc, 0, this.Count ); } public Io.Result StreamWrite( Stream outStream, FileContent fc, int start, int count ) { Io.Result rtn = Io.Result.NoAction; if ( fc == FileContent.FileHdr ) return rtn; if ( fc == FileContent.All || fc == FileContent.SwpAll || fc == FileContent.SwpHdr ) { rtn = StreamWriteHdr( outStream ); if ( rtn == Io.Result.BadFormat ) { string msg = "Sweep.StreamWrite(Stream,FileContent,int,int): 'Bad Format' signal from Sweep.StreamWriteHdr(Stream)"; throw new SimFileException( msg ); } } if ( fc != FileContent.SwpHdr ) { StreamWriteData( outStream, fc, start, count ); rtn = Io.Result.OK; } return rtn; } // method StreamWrite public Io.Result StreamWriteHdr( Stream outStream ) { // Prepare & write the fixed-length segment of the sweep header. byte[] bufSweepHdr = new byte[ nBytesSweepHdr ]; int nDx = 0; if ( nSamples < 0 || nSweepIds < 0 || nLocas < 0 ) return Io.Result.BadFormat; ByteArrayConverter.SetInt( bufSweepHdr, ref nDx, nSamples ); ByteArrayConverter.SetInt( bufSweepHdr, ref nDx, acqNum ); // deprecated ByteArrayConverter.SetInt( bufSweepHdr, ref nDx, nSweepIds ); ByteArrayConverter.SetInt( bufSweepHdr, ref nDx, nLocas ); // Set some data we don't care about. Array.Copy( sweepHdrExtra, 0, bufSweepHdr, nDx, nBytesExtraField ); nDx += nBytesExtraField; if ( nFileChars < 0 || nDescChars < 0 ) return Io.Result.BadFormat; ByteArrayConverter.SetInt( bufSweepHdr, ref nDx, nFileChars ); ByteArrayConverter.SetInt( bufSweepHdr, ref nDx, nDescChars ); outStream.Write( bufSweepHdr, 0, nBytesSweepHdr ); // Prepare & write the variable-length segment of the sweep header. int nBytesSweepAux = ByteSizeAux(); byte[] bufSweepAux = new byte[ nBytesSweepAux ]; nDx = 0; for ( int i = 0; i < nSweepIds; ++i ) { ByteArrayConverter.SetInt( bufSweepAux, ref nDx, SweepIds[i] ); } for ( int i = 0; i < nLocas; ++i ) { ByteArrayConverter.SetInt( bufSweepAux, ref nDx, Locas[i] ); } ByteArrayConverter.SetString( bufSweepAux, ref nDx, fileName ); ByteArrayConverter.SetString( bufSweepAux, ref nDx, fileDesc ); outStream.Write( bufSweepAux, 0, nBytesSweepAux ); return Io.Result.OK; } // method StreamWriteHdr public void StreamWriteData( Stream outStream, FileContent fc ) { StreamWriteData( outStream, fc, 0, this.Count ); } public void StreamWriteData( Stream outStream, FileContent fc, int start, int count ) { // Prepare and write the Sweep data. // Review this part later. Not sure this index-changing is all good. // .. Review this with all Stream Io methods. int myStart = 0 < start ? start : 0; int myCount = 0 < count ? count : 0; myStart = myStart < this.Count ? myStart : this.Count; myCount = myStart + myCount < this.Count ? myCount : this.Count; int nBytesData = myCount; int nDx = 0; switch ( fc ) { case FileContent.All : case FileContent.SwpAll : case FileContent.Data : nBytesData *= nBytesPerSample; break; case FileContent.SignalData : nBytesData *= nBytesSignalPerSample; break; case FileContent.IntegerData : nBytesData *= nBytesIntegerPerSample; break; default : return; } byte[] bufSweepData = new byte[nBytesData]; for ( int i = myStart; i < myCount; ++i ) { Sample sample = this[i]; if ( fc != FileContent.IntegerData ) { ByteArrayConverter.SetPairFloat( bufSweepData, ref nDx, sample.A ); ByteArrayConverter.SetPairFloat( bufSweepData, ref nDx, sample.B ); ByteArrayConverter.SetPairFloat( bufSweepData, ref nDx, sample.C ); ByteArrayConverter.SetPairFloat( bufSweepData, ref nDx, sample.D ); ByteArrayConverter.SetPairFloat( bufSweepData, ref nDx, sample.E ); } if ( fc != FileContent.SignalData ) { ByteArrayConverter.SetShort( bufSweepData, ref nDx, sample.one ); ByteArrayConverter.SetShort( bufSweepData, ref nDx, sample.two ); ByteArrayConverter.SetShort( bufSweepData, ref nDx, sample.three ); ByteArrayConverter.SetShort( bufSweepData, ref nDx, sample.four ); } } outStream.Write( bufSweepData, 0, nBytesData ); } // method StreamWriteData public Io.Result StreamRead( Stream inStream, FileContent fc ) { return StreamRead( inStream, fc, 0, this.Count ); } /* * Caller manages starting condition of the object. * inStream underflow => return Io.Result.Underflow * inStream overflow => return Io.Result.Overflow * .. otherwise return IoResult.OK */ public Io.Result StreamRead( Stream inStream, FileContent fc, int start, int count ) { Io.Result rtn = Io.Result.NoAction; if ( fc == FileContent.FileHdr ) return rtn; if ( fc == FileContent.All || fc == FileContent.SwpAll || fc == FileContent.SwpHdr ) { rtn = StreamReadHdr( inStream ); switch ( rtn ) { case Io.Result.BadFormat : case Io.Result.Underflow : string tag = Io.GetResultTag( rtn ); string msg = "Sweep.StreamRead(Stream,FileContent,int,int): '"+tag+"' signal from Sweep.StreamReadHdr"; throw new SimFileException( msg ); case Io.Result.Overflow : // Leave the overflow signal active: Let data method modify, or let caller decide what to do. case Io.Result.OK : break; } } if ( fc != FileContent.SwpHdr ) { rtn = StreamReadData( inStream, fc, start, count ); } return rtn; } // method StreamRead public Io.Result StreamReadHdr( Stream inStream ) { if ( inStream.Length - inStream.Position < nBytesSweepHdr ) return Io.Result.Underflow; // Read & parse the fixed-length segment of the Sweep header. int nDx = 0; byte[] bufSweepHdr = new byte[nBytesSweepHdr]; Io.Result rtn = StreamProcessor.ReadByteStream(bufSweepHdr, 0, nBytesSweepHdr, inStream); if ( rtn == Io.Result.BadIndex ) { string msg = "Sweep.StreamReadHdr(Stream): 'Bad Index' signal from StreamProcessor.ReadByteStream"; throw new SimFileException( msg ); } nSamples = ByteArrayConverter.GetInt( bufSweepHdr, ref nDx ); acqNum = ByteArrayConverter.GetInt( bufSweepHdr, ref nDx ); // deprecated nSweepIds = ByteArrayConverter.GetInt( bufSweepHdr, ref nDx ); nLocas = ByteArrayConverter.GetInt( bufSweepHdr, ref nDx ); if ( nSamples < 0 || nSweepIds < 0 || nLocas < 0 ) return Io.Result.BadFormat; // Get some data we don't care about but need to save. for ( int i = 0; i < nBytesExtraField; ++i ) { sweepHdrExtra[i] = bufSweepHdr[nDx + i]; } nDx += nBytesExtraField; nFileChars = ByteArrayConverter.GetInt( bufSweepHdr, ref nDx ); nDescChars = ByteArrayConverter.GetInt( bufSweepHdr, ref nDx ); if ( nFileChars < 0 || nDescChars < 0 ) return Io.Result.BadFormat; int nBytesSweepAux = ByteSizeAux(); if ( inStream.Length - inStream.Position < nBytesSweepAux ) return Io.Result.Underflow; // Read & parse the variable-length segment of the sweep header. nDx = 0; byte[] bufSweepAux = new byte[nBytesSweepAux]; rtn = StreamProcessor.ReadByteStream( bufSweepAux, 0, nBytesSweepAux, inStream ); if ( rtn == Io.Result.BadIndex ) { string msg = "Sweep.StreamReadHdr(Stream): 'Bad Index' signal from StreamProcessor.ReadByteStream"; throw new SimFileException( msg ); } for ( long i = 0; i < nSweepIds; ++i ) { SweepIds.Add( ByteArrayConverter.GetInt( bufSweepAux, ref nDx ) ); } for (int i = 0; i < nLocas; ++i) { Locas.Add( ByteArrayConverter.GetInt( bufSweepAux, ref nDx ) ); } fileName = ByteArrayConverter.GetString( bufSweepAux, ref nDx, nFileChars ); fileDesc = ByteArrayConverter.GetString( bufSweepAux, ref nDx, nDescChars ); if ( inStream.Position < inStream.Length ) return Io.Result.Overflow; return Io.Result.OK; } // method StreamReadHdr public Io.Result StreamReadData( Stream inStream, FileContent fc ) { return StreamReadData( inStream, fc, 0, this.Count ); } public Io.Result StreamReadData( Stream inStream, FileContent fc, int start, int count ) { if ( fc == FileContent.FileHdr || fc == FileContent.SwpHdr ) return Io.Result.NoAction; int myStart = 0 < start ? start : 0; int myCount = 0 < count ? count : 0; myStart = myStart < this.Count ? myStart : this.Count; int nBytesData = myCount; switch ( fc ) { case FileContent.All : case FileContent.SwpAll : case FileContent.Data : nBytesData *= nBytesPerSample; break; case FileContent.SignalData : nBytesData *= nBytesSignalPerSample; break; case FileContent.IntegerData : nBytesData *= nBytesIntegerPerSample; break; default : return 0; } if ( inStream.Length - inStream.Position < nBytesData ) return Io.Result.Underflow; // Read and parse the Sweep data. int nDx = 0; byte[] bufSweepData = new byte[ nBytesData ]; Io.Result rtn = StreamProcessor.ReadByteStream( bufSweepData, 0, nBytesData, inStream ); if ( rtn == Io.Result.BadIndex ) { string msg = "Sweep.StreamReadData(Stream,FileContent,int,int): 'Bad Index' signal from StreamProcessor.ReadByteStream"; throw new SimFileException( msg ); } for ( int i = myStart; i < myCount; ++i ) { Sample sample = i < this.Count ? this[i] : new Sample(); if ( fc != FileContent.IntegerData ) { sample.A = ByteArrayConverter.GetPairFloat( bufSweepData, ref nDx ); sample.B = ByteArrayConverter.GetPairFloat( bufSweepData, ref nDx ); sample.C = ByteArrayConverter.GetPairFloat( bufSweepData, ref nDx ); sample.D = ByteArrayConverter.GetPairFloat( bufSweepData, ref nDx ); sample.E = ByteArrayConverter.GetPairFloat( bufSweepData, ref nDx ); } if ( fc != FileContent.SignalData ) { sample.one = ByteArrayConverter.GetShort( bufSweepData, ref nDx ); sample.two = ByteArrayConverter.GetShort( bufSweepData, ref nDx ); sample.three= ByteArrayConverter.GetShort( bufSweepData, ref nDx ); sample.four = ByteArrayConverter.GetShort( bufSweepData, ref nDx ); } if ( i < this.Count ) { this[i] = sample; } else { this.Add( sample ); } } if ( inStream.Position < inStream.Length ) return Io.Result.Overflow; return Io.Result.OK; } // method StreamReadData private int ByteSize() { return Count * nBytesPerSample + nBytesSweepHdr + ByteSizeAux(); } private int ByteSizeAux() { return ( nSweepIds + nLocas ) * sizeof( Int32 ) + ( nFileChars + nDescChars ) * sizeof( char ) ; } public override string ToString() { int count = ((List) this).Count; string rtn = " "; rtn += nSamples.ToString() + ", "; rtn += SweepIds.ToString() + ", "; rtn += Locas.ToString() + ", "; rtn += fileName + ", "; rtn += fileDesc + " | "; for( int i = 0; i < count; ++i ) { rtn += ((List) this)[i].ToString(); if ( i + 1 < count ) { rtn += " | "; } } return rtn; } // method toString #endregion Methods #region Properties of class Sweep // public int NbrSamples { get { return nSamples; } set { nSamples = value; } } public int NbrFileChars { get { return nFileChars; } } public int NbrDescChars { get { return nDescChars; } } public string FileName { get { return fileName; } set { fileName = value; nFileChars = fileName.Length; } } public string FileDesc { get { return fileDesc; } set { fileDesc = value; nDescChars = fileDesc.Length; } } // #endregion #region Data of class Sweep // Fixed-length info private int nSamples; private int acqNum; // deprecated private int nSweepIds; private int nLocas; private byte[] sweepHdrExtra; private int nFileChars; private int nDescChars; // Variable-length info private List SweepIds; private List Locas; private string fileName; private string fileDesc; // #endregion } // class Sweep public class SimFileException : ApplicationException { public SimFileException( String message ) : base( message ) {} public SimFileException( String message, Exception inner ) : base( message, inner ) {} } // #endregion Contained classes #region Methods of class SimFile // public SimFile( List sweepSet ) { fileHdrExtra = new byte[nBytesExtraField]; Locas = new List(); fileName = ""; fileDesc = ""; mySweeps = sweepSet; byteBlock = new List(); legacyFileVersion = 0; } public SimFile() { fileHdrExtra = new byte[nBytesExtraField]; Locas = new List(); fileName = ""; fileDesc = ""; mySweeps = new List(); byteBlock = new List(); legacyFileVersion = 0; } /* * All StreamWrite methods send data from a memory object, to an output stream. */ public Io.Result StreamWrite( Stream outStream, FileContent fc ) { return StreamWrite( outStream, fc, 0, mySweeps.Count ); } /* * start, count represent sample units (not bytes !). */ public Io.Result StreamWrite( Stream outStream, FileContent fc, int start, int count ) { Io.Result rtn = Io.Result.OK; if ( fc == FileContent.FileHdr || fc == FileContent.All ) { rtn = StreamWriteHdr( outStream ); if ( rtn == Io.Result.BadFormat ) { string msg = "SimFile.StreamWrite(Stream,FileContent,int,int): 'Bad Format' signal from SimFile.StreamWriteHdr"; throw new SimFileException( msg ); } } if ( fc != FileContent.FileHdr ) { rtn = StreamWriteData( outStream, fc, start, count ); } return rtn; } // method StreamWrite public Io.Result StreamWriteHdr( Stream outStream ) { // Prepare & write the fixed-length segment of the file header. byte[] bufFileHdr = new byte[ nBytesFileHdr ]; int nDx = 0; if ( nSweeps < 0 || nLocas < 0 ) return Io.Result.BadFormat; ByteArrayConverter.SetInt( bufFileHdr, ref nDx, nSweeps ); ByteArrayConverter.SetInt( bufFileHdr, ref nDx, nLocas ); // Set some data we don't care about. Array.Copy( fileHdrExtra, 0, bufFileHdr, nDx, nBytesExtraField ); nDx += nBytesExtraField; if ( nFileChars < 0 || nDescChars < 0 ) return Io.Result.BadFormat; ByteArrayConverter.SetInt( bufFileHdr, ref nDx, nFileChars ); ByteArrayConverter.SetInt( bufFileHdr, ref nDx, nDescChars ); outStream.Write( bufFileHdr, 0, nBytesFileHdr ); // Prepare & write the variable-length segment of the file header. int nBytesFileAux = ByteSizeAux(); byte[] bufFileAux = new byte[nBytesFileAux]; nDx = 0; for ( int i = 0; i < nLocas; ++i ) { ByteArrayConverter.SetInt( bufFileAux, ref nDx, Locas[i] ); } ByteArrayConverter.SetString( bufFileAux, ref nDx, fileName ); ByteArrayConverter.SetString( bufFileAux, ref nDx, fileDesc ); outStream.Write( bufFileAux, 0, nBytesFileAux ); return Io.Result.OK; } // method StreamWriteHdr public Io.Result StreamWriteData( Stream outStream, FileContent fc ) { return StreamWriteData( outStream, fc, 0, mySweeps.Count ); } /* * start, count represent sample units (not bytes !). */ public Io.Result StreamWriteData( Stream outStream, FileContent fc, int start, int count ) { Io.Result rtn = Io.Result.NoAction; if ( fc == FileContent.FileHdr ) return rtn; int myStart = 0 < start ? start : 0; int myCount = 0 < count ? count : 0; myStart = myStart < mySweeps.Count ? myStart : mySweeps.Count; myCount = myStart + myCount < mySweeps.Count ? myCount : mySweeps.Count; for ( int i = myStart; i < myCount; ++i ) { rtn = mySweeps[i].StreamWrite( outStream, fc ); switch ( rtn ) { case Io.Result.OK : break; default : string tag = Io.GetResultTag( rtn ); string msg = "SimFile.StreamWriteData(Stream,FileContent,int,int): '"+tag+"' signal from Sweep.StreamWrite"; throw new SimFileException( msg ); } } return rtn; } // method StreamWriteData /* * All StreamRead methods send data from a stream, to an object in memory. */ public Io.Result StreamRead( Stream inStream, FileContent fc ) { return StreamRead( inStream, fc, 0, mySweeps.Count ); } /* * start, count represent sample units (not bytes !). */ public Io.Result StreamRead( Stream inStream, FileContent fc, int start, int count ) { Io.Result rtn = Io.Result.OK; if ( fc == FileContent.FileHdr || fc == FileContent.All ) { rtn = StreamReadHdr( inStream ); switch ( rtn ) { case Io.Result.BadFormat : case Io.Result.Underflow : string tag = Io.GetResultTag( rtn ); string msg = "SimFile.StreamRead(Stream,FileContent,int,int): '"+tag+"' signal from SimFile.StreamReadHdr"; throw new SimFileException( msg ); case Io.Result.Overflow : // May still need to read Sweeps. // Let the overflow be returned to the caller, or be modified by data read. case Io.Result.OK : break; } } if ( fc != FileContent.FileHdr ) { rtn = StreamReadData( inStream, fc, start, count ); switch ( rtn ) { case Io.Result.Overflow : // Supposed to be finished. string tag = Io.GetResultTag( rtn ); string msg = "SimFile.StreamRead(Stream,FileContent,int,int): '"+tag+"' signal from SimFile.StreamReadData"; throw new SimFileException( msg ); case Io.Result.OK : break; } } return rtn; } // method StreamRead public Io.Result StreamReadHdr( Stream inStream ) { if ( inStream.Length - inStream.Position < nBytesFileHdr ) return Io.Result.Underflow; // Read & parse the fixed-length segment of the file header. int nDx = 0; byte[] bufFileHdr = new byte[nBytesFileHdr]; Io.Result rtn = StreamProcessor.ReadByteStream( bufFileHdr, 0, nBytesFileHdr, inStream ); if ( rtn == Io.Result.BadIndex ) { string tag = Io.GetResultTag( rtn ); string msg = "SimFile.StreamReadHdr(Stream): '" + tag + "' signal from StreamProcessor.ReadByteStream"; throw new SimFileException( msg ); } nSweeps = ByteArrayConverter.GetInt( bufFileHdr, ref nDx ); nLocas = ByteArrayConverter.GetInt( bufFileHdr, ref nDx ); if (nSweeps < 0 || nLocas < 0) return Io.Result.BadFormat; // Get some data we don't care about but need to save. for ( int i = 0; i < nBytesExtraField; ++i ) { fileHdrExtra[i] = bufFileHdr[nDx + i]; } nDx += nBytesExtraField; nFileChars = ByteArrayConverter.GetInt( bufFileHdr, ref nDx ); nDescChars = ByteArrayConverter.GetInt( bufFileHdr, ref nDx ); if (nFileChars < 0 || nDescChars < 0) return Io.Result.BadFormat; int nBytesFileAux = ByteSizeAux(); if ( inStream.Length - inStream.Position < nBytesFileAux ) return Io.Result.Underflow; // Read & parse the variable-length segment of the sweep header. nDx = 0; byte[] bufFileAux = new byte[ nBytesFileAux ]; rtn = StreamProcessor.ReadByteStream( bufFileAux, 0, nBytesFileAux, inStream ); if ( rtn == Io.Result.BadIndex ) { string tag = Io.GetResultTag( rtn ); string msg = "SimFile.StreamReadHdr(Stream): '" + tag + "' signal from StreamProcessor.ReadByteStream"; throw new SimFileException( msg ); } for ( int i = 0; i < nLocas; ++i ) { Locas.Add( ByteArrayConverter.GetInt( bufFileAux, ref nDx ) ); } fileName = ByteArrayConverter.GetString( bufFileAux, ref nDx, nFileChars ); fileDesc = ByteArrayConverter.GetString( bufFileAux, ref nDx, nDescChars ); if ( inStream.Position + 1 < inStream.Length ) return Io.Result.Overflow; return Io.Result.OK; } // method StreamReadHdr public Io.Result StreamReadData( Stream inStream, FileContent fc ) { return StreamReadData( inStream, fc, 0, mySweeps.Count ); } /* * Caller must manage the starting size of mySweeps, and the ending value of nSweeps. * start, count represent sample units (not bytes !). */ public Io.Result StreamReadData( Stream inStream, FileContent fc, int start, int count ) { Io.Result rtn = Io.Result.NoAction; if ( fc == FileContent.FileHdr ) return rtn; int myStart = 0 < start ? start : 0; myStart = myStart < mySweeps.Count ? myStart : mySweeps.Count; // Read and parse Sweep data from inStream. // Note: requires that the sweep header was previously read in (so that NbrSamples is set). for ( int i = myStart; i < count; ++i ) { bool xFlg = false; if ( i < mySweeps.Count ) { // Modify existing Sweep object. Sweep sweep = mySweeps[i]; rtn = sweep.StreamRead( inStream, fc, 0, sweep.NbrSamples ); switch ( rtn ) { case Io.Result.Underflow : xFlg = true; break; case Io.Result.Overflow : if ( i + 1 < mySweeps.Count ) { rtn = Io.Result.OK; } else { //return rtn; // Supposed to be finished. xFlg = true; // Supposed to be finished. } break; case Io.Result.NoAction : rtn = Io.Result.OK; break; case Io.Result.OK : break; } if ( xFlg ) { string tag = Io.GetResultTag( rtn ); string msg = "SimFile.StreamReadData(Stream,FileContent,int,int): '"+tag+"' signal from Sweep.StreamRead"; throw new SimFileException( msg ); } mySweeps[i] = sweep; } else { Sweep sweep = new Sweep(); rtn = sweep.StreamReadHdr( inStream ); switch ( rtn ) { case Io.Result.BadFormat : case Io.Result.Underflow : xFlg = true; break; case Io.Result.Overflow : if (( i + 1 < count ) || ( fc != FileContent.SwpHdr )) { rtn = Io.Result.OK; // No problem, still have to read Sweeps. } else { xFlg = true; // Supposed to be finished. } break; case Io.Result.OK : break; } if ( xFlg ) { string tag = Io.GetResultTag( rtn ); string msg = "SimFile.StreamReadData(Stream,FileContent,int,int): '"+tag+"' signal from Sweep.StreamReadHdr"; throw new SimFileException( msg ); } rtn = sweep.StreamReadData( inStream, fc, 0, sweep.NbrSamples ); switch ( rtn ) { case Io.Result.Underflow : xFlg = true; break; case Io.Result.Overflow : if ( i + 1 < count ) { rtn = Io.Result.OK; // No problem, still have to read Sweeps. } else { xFlg = true; // Supposed to be finished. } break; case Io.Result.NoAction : rtn = Io.Result.OK; break; case Io.Result.OK : break; } if ( xFlg ) { string tag = Io.GetResultTag( rtn ); string msg = "SimFile.StreamReadData(Stream,FileContent,int,int): '"+tag+"' signal from Sweep.StreamReadData"; throw new SimFileException( msg ); } mySweeps.Add(sweep); } } if ( inStream.Position < inStream.Length ) return Io.Result.Overflow; return rtn; } // method StreamReadData public Io.Result FileWrite( string fileSpec ) { File.Delete( fileSpec ); Io.Result rtn = Io.Result.OK; FileStream outStream = File.OpenWrite( fileSpec ); try { rtn = StreamWrite( outStream, FileContent.All ); } catch ( Exception ex ) { string msg = "Caught in SimFile.FileWrite(string) call StreamWrite(Stream, FileContent)"; throw new SimFileException( msg, ex ); } finally { outStream.Close(); } return rtn; } // method FileWrite public Io.Result FileRead( string fileSpec ) { mySweeps.Clear(); Io.Result rtn = Io.Result.OK; FileStream inStream = File.OpenRead( fileSpec ); try { rtn = StreamReadHdr( inStream ); switch ( rtn ) { case Io.Result.BadFormat : case Io.Result.Underflow : string tag = Io.GetResultTag( rtn ); string msg = "SimFile.FileRead(string): '"+tag+"' signal from SimFile.StreamReadHdr"; throw new SimFileException( msg ); case Io.Result.Overflow : // No problem, still need to read Sweeps. rtn = Io.Result.OK; break; case Io.Result.OK : break; } rtn = StreamReadData( inStream, FileContent.All, 0, nSweeps ); } catch ( Exception ex ) { throw new SimFileException("Caught in SimFile.FileRead", ex); } finally { inStream.Close(); } switch ( rtn ) { case Io.Result.Overflow : // Supposed to be finished. string tag = Io.GetResultTag( rtn ); string msg = "SimFile.FileRead(Stream,FileContent,int,int): '"+tag+"' signal from SimFile.StreamReadData"; throw new SimFileException( msg ); case Io.Result.OK : default : break; } return rtn; } // method FileRead /* * Populate the data member byteBlock, with object data corresponding to fc. */ public Io.Result LoadByteBlock( FileContent fc ) { byteBlock.Clear(); MemoryStream memStream = new MemoryStream(); Io.Result rtn = Io.Result.OK; try { if ( fc == FileContent.FileHdr || fc == FileContent.All ) { rtn = StreamWriteHdr( memStream ); if (rtn == Io.Result.BadFormat) { string tag = Io.GetResultTag( rtn ); string msg = "SimFile.LoadByteBlock(FileContent): '"+tag+"' signal from SimFile.StreamWriteHdr"; throw new SimFileException( msg ); } byteBlock.Add( memStream.ToArray() ); } if ( fc != FileContent.FileHdr ) { for ( int i = 0; i < mySweeps.Count; ++i ) { memStream.SetLength( 0 ); rtn = mySweeps[i].StreamWrite( memStream, fc ); // rtn == OK unless exception was thrown in callee. byteBlock.Add( memStream.ToArray() ); } } } catch ( Exception ex ) { throw new SimFileException("Caught in SimFile.LoadByteBlock(FileContent)", ex); } finally { memStream.Close(); } return rtn; // OK if no exception thrown. } // method LoadByteBlock /* * This has been adapted to serve two different but similar applications. * It reports the row and column size characteristics of byteBlock. * The return value represents the #rows and the width of the widest row (greatest #cols). * The two out values are to be interpreted as follows: * wmin is the width of the narrowest row (least #cols). * If extra is an empty array, then byteBlock is rectangular. * .. Otherwise, extra has a number of elements equal to the #rows, * .. .. and each element is the difference between wmin and the corresponding row's width. * (wmin and extra may be used directly by SimZip.Compress to form a header for a jagged array component.) */ public Pair GetByteBlockScale( out int wmin, out int[] extra ) { List eList = new List(); bool isJagged = false; int height = byteBlock.Count; int wmax = 0; wmin = byteBlock[0].Length; for ( int i = 0; i < height; ++i ) { int len = byteBlock[i].Length; if ( len < wmin ) wmin = len; if ( wmax < len ) wmax = len; } for ( int i = 0; i < height; ++i ) { int dif = byteBlock[i].Length - wmin; if ( 0 < dif ) isJagged = true; eList.Add(dif); } if ( isJagged ) { extra = new int[ eList.Count ]; eList.CopyTo( extra ); } else { extra = new int[0]; } return new Pair( height, wmax ); } // method GetByteBlockScale private int ByteSizeAux() { return nLocas * sizeof(Int32) + (nFileChars + nDescChars) * sizeof(char) ; } public override string ToString() { int count = mySweeps.Count; string rtn = " "; rtn += nSweeps.ToString() + ", "; rtn += Locas.ToString() + ", "; rtn += fileName + ", "; rtn += fileDesc + ", "; for (int i = 0; i < count; ++i) { rtn += mySweeps[i].ToString(); if (i + 1 < count) rtn += " | "; } return rtn; } // method ToString // #endregion Methods #region Properties of class SimFile // public int LegacyFileVersion { get {return legacyFileVersion;} set {legacyFileVersion = value;} } public int NbrSweeps { get {return nSweeps;} set {nSweeps = value;} } // #endregion #region Data of class SimFile // Memory-only data private int legacyFileVersion; // Fixed-length info private int nSweeps; private int nLocas; private byte[] fileHdrExtra; private int nFileChars; private int nDescChars; // Variable-length info private List Locas; private string fileName; private string fileDesc; // Sweep data protected List mySweeps; protected List byteBlock; // #endregion } // class SimFile } // namespace Compress