/// <summary> /// Initialize this object from another object. /// This ugly hack allows us to read the opaque objects and store references to /// the subsystem data in them before parsing the actual subsystem data (which /// comes later in the file). /// </summary> /// <param name="data">Another subsystem data.</param> public void Set(SubsystemData data) { _realData = new RealSubsystemData( data.ClassInformation, data.ObjectInformation, data.Data); }
private static List <RawVariable> ReadRawVariables(byte[] bytes, SubsystemData subsystemData) { using var stream = new MemoryStream(bytes); using var reader = new BinaryReader(stream); reader.ReadBytes(8); return(MatFileReader.ReadRawVariables(reader, -1, subsystemData)); }
/// <summary> /// Initializes a new instance of the <see cref="OpaqueLink"/> class. /// </summary> /// <param name="name">Name of the object.</param> /// <param name="typeDescription">Description of object's class.</param> /// <param name="className">Name of the object's class.</param> /// <param name="dimensions">Dimensions of the object.</param> /// <param name="data">Raw data containing links to object's storage.</param> /// <param name="indexToObjectId">Links to object's storage.</param> /// <param name="classIndex">Index of object's class.</param> /// <param name="subsystemData">Reference to global subsystem data.</param> public OpaqueLink( string name, string typeDescription, string className, int[] dimensions, DataElement data, int[] indexToObjectId, int classIndex, SubsystemData subsystemData) : base(name, typeDescription, className, dimensions, data) { IndexToObjectId = indexToObjectId ?? throw new ArgumentNullException(nameof(indexToObjectId)); ClassIndex = classIndex; this.subsystemData = subsystemData ?? throw new ArgumentNullException(nameof(subsystemData)); }
/// <summary> /// Read subsystem data from a given byte array. /// </summary> /// <param name="bytes">Byte array with the data.</param> /// <param name="subsystemData"> /// Link to the existing subsystem data; this will be put in nested OpaqueLink objects /// and later replaced with the subsystem data that we are currently reading.</param> /// <returns>Subsystem data read.</returns> public static SubsystemData Read(byte[] bytes, SubsystemData subsystemData) { var rawVariables = ReadRawVariables(bytes, subsystemData); // Parse subsystem data. var mainVariable = rawVariables[0].DataElement as IStructureArray ?? throw new HandlerException("Subsystem data must be a structure array."); var mcosData = mainVariable["MCOS", 0] as Opaque ?? throw new HandlerException("MCOS data must be an opaque object."); var opaqueData = mcosData.RawData as ICellArray ?? throw new HandlerException("Opaque data must be a cell array."); var info = (opaqueData[0] as IArrayOf <byte>)?.Data ?? throw new HandlerException("Opaque data info must be a byte array."); var(offsets, position) = ReadOffsets(info, 0); var fieldNames = ReadFieldNames(info, position, offsets[1]); var numberOfClasses = ((offsets[3] - offsets[2]) / 16) - 1; var classIdToName = ReadClassIdToName(info, offsets, fieldNames, numberOfClasses); var numberOfEmbeddedObjects = (offsets[4] - offsets[3] - 8) / 16; var embeddedObjectPositionsToValues = ReadEmbeddedObjectPositionsToValues(info, offsets, numberOfEmbeddedObjects); var numberOfObjects = ((offsets[5] - offsets[4]) / 24) - 1; var objectClasses = ReadObjectClassInformations(info, offsets, numberOfObjects); var numberOfObjectPositions = objectClasses.Values.Count(x => x.ObjectPosition != 0); var objectPositionsToValues = ReadObjectPositionsToValues(info, offsets, numberOfObjectPositions); var(classInformation, objectInformation) = GatherClassAndObjectInformation( classIdToName, fieldNames, objectClasses, objectPositionsToValues, embeddedObjectPositionsToValues); var allFields = objectInformation.Values.SelectMany(obj => obj.FieldLinks.Values); var data = new Dictionary <int, IArray>(); foreach (var i in allFields) { data[i] = TransformOpaqueData(opaqueData[i + 2], subsystemData); } return(new SubsystemData(classInformation, objectInformation, data)); }
private static IArray TransformOpaqueData(IArray array, SubsystemData subsystemData) { if (array is MatNumericalArrayOf <uint> uintArray) { if (uintArray.Data[0] == 3707764736u) { var(dimensions, indexToObjectId, classIndex) = DataElementReader.ParseOpaqueData(uintArray.Data); return(new OpaqueLink( uintArray.Name, string.Empty, string.Empty, dimensions, array as DataElement, indexToObjectId, classIndex, subsystemData)); } } return(array); }
/// <summary> /// Initializes a new instance of the <see cref="DataElementReader"/> class. /// </summary> /// <param name="subsystemData">Reference to file's SubsystemData.</param> public DataElementReader(SubsystemData subsystemData) { this.subsystemData = subsystemData ?? throw new ArgumentNullException(nameof(subsystemData)); }
/// <summary> /// Read raw variables from a .mat file. /// </summary> /// <param name="reader">Binary reader.</param> /// <param name="subsystemDataOffset">Offset to the subsystem data to use (read from the file header).</param> /// <returns>Raw variables read.</returns> internal static List<RawVariable> ReadRawVariables(BinaryReader reader, long subsystemDataOffset) { var subsystemData = new SubsystemData(); return ReadRawVariables(reader, subsystemDataOffset, subsystemData); }
/// <summary> /// Read a sequence of raw variables from .mat file. /// </summary> /// <param name="reader">Reader.</param> /// <param name="subsystemDataOffset">Offset of subsystem data in the file; /// we need it because we may encounter it during reading, and /// the subsystem data should be parsed in a special way.</param> /// <param name="subsystemData"> /// Link to the current file's subsystem data structure; initially it has dummy value /// which will be replaced after we parse the whole subsystem data.</param> /// <returns>List of "raw" variables; the actual variables are constructed from them later.</returns> internal static List<RawVariable> ReadRawVariables(BinaryReader reader, long subsystemDataOffset, SubsystemData subsystemData) { var variables = new List<RawVariable>(); var dataElementReader = new DataElementReader(subsystemData); while (true) { try { var position = reader.BaseStream.Position; var dataElement = dataElementReader.Read(reader); if (position == subsystemDataOffset) { var subsystemDataElement = dataElement as IArrayOf<byte> ?? throw new HandlerException("Cannot parse subsystem data element."); var newSubsystemData = ReadSubsystemData(subsystemDataElement.Data, subsystemData); subsystemData.Set(newSubsystemData); } else { variables.Add(new RawVariable(position, dataElement)); } } catch (EndOfStreamException) { break; } } return variables; }
private static SubsystemData ReadSubsystemData(byte[] bytes, SubsystemData subsystemData) { return SubsystemDataReader.Read(bytes, subsystemData); }
/// <summary> /// Read subsystem data from a given byte array. /// </summary> /// <param name="bytes">Byte array with the data.</param> /// <param name="subsystemData"> /// Link to the existing subsystem data; this will be put in nested OpaqueLink objects /// and later replaced with the subsystem data that we are currently reading.</param> /// <returns>Subsystem data read.</returns> public static SubsystemData Read(byte[] bytes, SubsystemData subsystemData) { List <RawVariable> rawVariables = null; using (var stream = new MemoryStream(bytes)) { using (var reader = new BinaryReader(stream)) { reader.ReadBytes(8); rawVariables = MatFileReader.ReadRawVariables(reader, -1, subsystemData); } } // Parse subsystem data. var mainVariable = rawVariables[0].DataElement as IStructureArray; var mcosData = mainVariable["MCOS", 0] as Opaque; var opaqueData = mcosData.RawData as ICellArray; var info = (opaqueData[0] as IArrayOf <byte>).Data; var(offsets, position) = ReadOffsets(info, 0); var fieldNames = ReadFieldNames(info, position, offsets[1]); var numberOfClasses = ((offsets[3] - offsets[2]) / 16) - 1; Dictionary <int, string> classIdToName = null; using (var stream = new MemoryStream(info, offsets[2], offsets[3] - offsets[2])) { using (var reader = new BinaryReader(stream)) { classIdToName = ReadClassNames(reader, fieldNames, numberOfClasses); } } var numberOfObjects = ((offsets[5] - offsets[4]) / 24) - 1; Dictionary <int, (int, int)> objectClasses = null; using (var stream = new MemoryStream(info, offsets[4], offsets[5] - offsets[4])) { using (var reader = new BinaryReader(stream)) { objectClasses = ReadObjectClasses(reader, numberOfObjects); } } Dictionary <int, Dictionary <int, int> > objectToFields = null; using (var stream = new MemoryStream(info, offsets[5], offsets[6] - offsets[5])) { using (var reader = new BinaryReader(stream)) { objectToFields = ReadObjectToFieldsMapping(reader, numberOfObjects); } } var(classInformation, objectInformation) = GatherClassAndObjectInformation( classIdToName, fieldNames, objectClasses, objectToFields); var allFields = objectInformation.Values.SelectMany(obj => obj.FieldLinks.Values); var data = new Dictionary <int, IArray>(); foreach (var i in allFields) { data[i] = TransformOpaqueData(opaqueData[i + 2], subsystemData); } return(new SubsystemData(classInformation, objectInformation, data)); }
/// <summary> /// Initialize this object from another object. /// This ugly hack allows us to read the opaque objects and store references to /// the subsystem data in them before parsing the actual subsystem data (which /// comes later in the file). /// </summary> /// <param name="data">Another subsystem data.</param> public void Set(SubsystemData data) { this.ClassInformation = data.ClassInformation; this.ObjectInformation = data.ObjectInformation; this.Data = data.Data; }