Commit 74e040b5 authored by Matthew Dawson's avatar Matthew Dawson
Browse files

Add a decoder for Simulink derived MAT files.

Simulink will encode its MAT file using a form of base64, using uuencode's
key.  SimulinkDecoder is a very simple stream based class to parse it.
parent be24249f
Loading
Loading
Loading
Loading
+68 −0
Original line number Diff line number Diff line
/*
 * Copyright 2014 Matthew Dawson <matthew@mjdsystems.ca>
 */
package ca.mjdsystems.jmatio.io;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

/** This class decodes the Simulink base64 representation of a MAT file.
 *
 * @author Matthew Dawson <matthew@mjdsystems.ca>
 */
public class SimulinkDecoder extends InputStream
{
    public SimulinkDecoder(String input)
    {
        this.input = input.getBytes();
        for (byte i = 0; i < 64; ++i) {
            decoderRing.put((byte)(i + ' '), i);
        }
        System.out.println("S " + input.length() + " B " + this.input.length);
    }

    @Override
    public int read() throws IOException
    {
        try {
            int ret;
            switch (pos % 4) {
                case 0: {
                    byte first = decoderRing.get(input[pos++]);
                    byte second = decoderRing.get(input[pos++]);

                    ret = (first << 2) | (second >> 4);
                    leftover = (byte) (second & 0x0f);
                    break;
                }
                case 2: {
                    byte next = decoderRing.get(input[pos++]);

                    ret = (leftover << 4) | (next >> 2);
                    leftover = (byte) (next & 0x03);
                    break;
                }
                case 3: {
                    byte next = decoderRing.get(input[pos++]);
                    ret = (leftover << 6) | next;
                    break;
                }
                default:
                    throw new RuntimeException("Case " + (pos % 4));
            }

            return ret;
        } catch (ArrayIndexOutOfBoundsException ex) {
            pos = -1; // Ensure that the exception will be re-thrown, avoiding a buffer overflow.
            throw new EOFException("No more bytes!");
        }
    }

    private final byte[] input;
    private int pos;
    private byte leftover;
    final private Map<Byte, Byte> decoderRing = new HashMap<Byte, Byte>();
}
+78 −0

File added.

Preview size limit exceeded, changes collapsed.

+19.7 KiB

File added.

No diff preview for this file type.