Commit 0378fc0b authored by Matthew Dawson's avatar Matthew Dawson
Browse files

Start reading more property related fields.

To support multiple objects with differing field values for the same class
type, it is now necessary to actually parse segment 4 and act accordingly.
Thus do that, and add a test to ensure the behaviour is correct.
parent e8b47c46
Loading
Loading
Loading
Loading
+49 −1
Original line number Diff line number Diff line
@@ -518,7 +518,7 @@ public class MatFileReader

            MatMCOSObjectInformation objHolder = objectInfoList.get(objectId - 1);
            if (objHolder == null) {
                objHolder = new MatMCOSObjectInformation(classNamesList.get(classIndex - 1), classIndex, objectId);
                objHolder = new MatMCOSObjectInformation(classNamesList.get(classIndex - 1), classIndex, objectId, segment4Index);
                objectInfoList.put(objectId - 1, objHolder);
            }

@@ -529,6 +529,54 @@ public class MatFileReader
            throw new IllegalStateException("Data from the object section was not all read!  At: " + mcosDataBuf.position() + ", wanted: " + segmentIndexes[3]);
        }

        // Fourth segment.  Contains the regular properties for objects.
        // There are 8 unknown bytes.  Ensure they are 0.
        if (mcosDataBuf.getLong() != 0) {
            throw new IllegalStateException("MAT file's MCOS data has different byte values for unknown fields!  Aborting!");
        }
        List<Map<String, MLArray>> segment4Properties = new ArrayList<Map<String, MLArray>>();
        int propertiesIndex = 0;
        while (mcosDataBuf.position() < segmentIndexes[4]) {
            Map<String, MLArray> properties = new HashMap<String, MLArray>();
            int propertiesCount = mcosDataBuf.getInt();
            for (int i = 0; i < propertiesCount; ++i) {
                int nameIndex = mcosDataBuf.getInt();
                int flag = mcosDataBuf.getInt();
                int heapIndex = mcosDataBuf.getInt();

                String propertyName = strs[nameIndex - 1];
                switch (flag) {
                    case 0:
                        properties.put(propertyName, new MLChar(propertyName, strs[heapIndex-1]));
                        break;
                    case 1:
                        properties.put(propertyName, mcosInfo.get(heapIndex+2));
                        break;
                    case 2:
                        // @todo: Handle a boolean.
                        throw new UnsupportedOperationException("Mat file parsing does not yet support booleans!");
                }
            }
            segment4Properties.add(properties);
            mcosDataBuf.position((mcosDataBuf.position() + 0x07) & ~0x07);
        }


        // Sanity check, position in the buffer should equal the start of the fourth segment!
        if (mcosDataBuf.position() != segmentIndexes[4]) {
            throw new IllegalStateException("Data from the properties section (2) was not all read!  At: " + mcosDataBuf.position() + ", wanted: " + segmentIndexes[4]);
        }

        // Now merge in the properties from segment 4 into object.
        for (MatMCOSObjectInformation it : objectInfoList.values()) {
            MLStructure objAttributes = it.structure;
            if (it.segment4PropertiesIndex > 0) {
                for (Map.Entry<String, MLArray> attribute : segment4Properties.get(it.segment4PropertiesIndex - 1).entrySet()) {
                    objAttributes.setField(attribute.getKey(), attribute.getValue());
                }
            }
        }

        // Finally, merge in attributes from the global grab bag.
        MLCell attribBag = (MLCell) mcosInfo.get(mcosInfo.getSize() -1); // Get the grab bag.
        for (MatMCOSObjectInformation it : objectInfoList.values()) {
+4 −2
Original line number Diff line number Diff line
@@ -3,7 +3,6 @@
 */
package ca.mjdsystems.jmatio.io;

import ca.mjdsystems.jmatio.types.MLArray;
import ca.mjdsystems.jmatio.types.MLStructure;

/**
@@ -11,16 +10,19 @@ import ca.mjdsystems.jmatio.types.MLStructure;
 * @author Matthew Dawson <matthew@mjdsystems.ca>
 */
class MatMCOSObjectInformation {
    MatMCOSObjectInformation(String className, int classId, int objectId)
    MatMCOSObjectInformation(String className, int classId, int objectId, int segment4PropertiesIndex)
    {
        this.className = className;

        this.objectId = objectId;
        this.classId = classId;

        this.segment4PropertiesIndex = segment4PropertiesIndex;
    }

    final String className;
    final int objectId;
    final int classId;
    final int segment4PropertiesIndex;
    final MLStructure structure = new MLStructure("", new int[]{1,1});
}
+51 −0
Original line number Diff line number Diff line
@@ -96,6 +96,57 @@ public class MatlabMCOSTest {
        assertThat(obj.getObject().getFieldNames().iterator().next(), is("test_text"));
    }

    @Test
    public void testParsingSimpleSingleTextMultipleMCOS() throws IOException
    {
        File file = fileFromStream("/mcos/simplesingletext_multiple.mat");
        MatFileReader reader = new MatFileReader(file);
        Map<String, MLArray> content = reader.getContent();

        assertThat(content.size(), is(3));

        MLObject obj = (MLObject) content.get("obj1");
        assertThat(obj, is(notNullValue()));

        assertThat(obj.getName(), is("obj1"));
        assertThat(obj.getClassName(), is("SimpleSingleText"));
        Collection<MLArray> fields = obj.getObject().getAllFields();
        assertThat(fields.size(), is(1));

        MLChar field = (MLChar) fields.toArray()[0];
        assertThat(field.getString(0), is("other text 1"));

        assertThat(obj.getObject().getFieldNames().iterator().next(), is("test_text"));


        obj = (MLObject) content.get("obj2");
        assertThat(obj, is(notNullValue()));

        assertThat(obj.getName(), is("obj2"));
        assertThat(obj.getClassName(), is("SimpleSingleText"));
        fields = obj.getObject().getAllFields();
        assertThat(fields.size(), is(1));

        field = (MLChar) fields.toArray()[0];
        assertThat(field.getString(0), is("Default text"));

        assertThat(obj.getObject().getFieldNames().iterator().next(), is("test_text"));


        obj = (MLObject) content.get("obj3");
        assertThat(obj, is(notNullValue()));

        assertThat(obj.getName(), is("obj3"));
        assertThat(obj.getClassName(), is("SimpleSingleText"));
        fields = obj.getObject().getAllFields();
        assertThat(fields.size(), is(1));

        field = (MLChar) fields.toArray()[0];
        assertThat(field.getString(0), is("other text 3"));

        assertThat(obj.getObject().getFieldNames().iterator().next(), is("test_text"));
    }

    private File fileFromStream(String location) throws IOException
    {
        String outname = location.replace("/", "_");
+1.69 KiB

File added.

No diff preview for this file type.