├── .ci └── ci.sh ├── .gitattributes ├── .gitignore ├── .travis.yml ├── CHANGES.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── META-INF └── MANIFEST.MF ├── MatlabClasses ├── HandleClass.m ├── OtherClass.m ├── SimpleEmpty.m ├── SimpleSingleText.m └── TestHandleClass.m ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── build.gradle ├── doc └── matfile_format.pdf ├── gradle.properties ├── gradle ├── spotless.eclipseformat.xml ├── spotless.importorder ├── spotless.license.java └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── matfilerw.png ├── matfilerw.svg └── src ├── main ├── assembly │ └── bundle.xml ├── java │ └── com │ │ └── jmatio │ │ ├── common │ │ ├── AbstractIterator.java │ │ ├── DeterministicKeyMap.java │ │ ├── ForwardingCollection.java │ │ ├── ForwardingMap.java │ │ ├── MatDataTypes.java │ │ └── util │ │ │ └── MLArrayQuery.java │ │ ├── io │ │ ├── MLObjectPlaceholder.java │ │ ├── MatFile.java │ │ ├── MatFileFilter.java │ │ ├── MatFileHeader.java │ │ ├── MatFileIncrementalWriter.java │ │ ├── MatFileReader.java │ │ ├── MatFileType.java │ │ ├── MatFileWriter.java │ │ ├── MatMCOSObjectInformation.java │ │ ├── MatTag.java │ │ ├── MatlabIOException.java │ │ ├── OSArrayTag.java │ │ ├── SimulinkDecoder.java │ │ ├── Unsafe9R.java │ │ └── stream │ │ │ ├── BufferedOutputStream.java │ │ │ ├── ByteBufferInputStream.java │ │ │ ├── DataOutputStream.java │ │ │ ├── HeapBufferDataOutputStream.java │ │ │ └── MatFileInputStream.java │ │ └── types │ │ ├── ByteStorageSupport.java │ │ ├── MLArray.java │ │ ├── MLCell.java │ │ ├── MLChar.java │ │ ├── MLDouble.java │ │ ├── MLEmptyArray.java │ │ ├── MLHandle.java │ │ ├── MLInt16.java │ │ ├── MLInt32.java │ │ ├── MLInt64.java │ │ ├── MLInt8.java │ │ ├── MLJavaObject.java │ │ ├── MLNumericArray.java │ │ ├── MLObject.java │ │ ├── MLSingle.java │ │ ├── MLSparse.java │ │ ├── MLStructure.java │ │ ├── MLStructureObjectBase.java │ │ ├── MLUInt16.java │ │ ├── MLUInt32.java │ │ ├── MLUInt64.java │ │ ├── MLUInt8.java │ │ └── Zeros.java └── main.iml └── test ├── java └── com │ └── jmatio │ ├── common │ └── util │ │ ├── DeterministicKeyMapTest.java │ │ └── MLArrayQueryTest.java │ ├── io │ ├── MatIOTest.java │ ├── MatlabMCOSTest.java │ ├── SimulinkMatTest.java │ └── StructureWithTimeseriesTest.java │ └── types │ └── MLNumericArrayTest.java ├── matlab └── com │ └── jmatio │ ├── TestMultiDimArray.m │ └── TestMultiDimComplexArray.m └── resources ├── SPM.mat ├── bigsparse.mat ├── cell.mat ├── emptyname.mat ├── handles.mat ├── int32.mat ├── int64.mat ├── int8.mat ├── java.mat ├── logical.mat ├── matnativedouble.mat ├── matnativedouble2.mat ├── mcos ├── handlesingle_multiple.mat ├── simpleempty.mat ├── simpleempty_multiple.mat ├── simplesingletext_multiple.mat ├── simplesingletext_multiplearray.mat └── simplesingletext_unmodified.mat ├── multiDimComplexMatrix.mat ├── multiDimMatrix.mat ├── nan.mat ├── object.mat ├── simplestruct.mat ├── simulink_tet_out.mat ├── single.mat ├── sparse.mat ├── timeseries.mat ├── uint32.mat ├── uint64.mat ├── uint8.mat ├── utf.m └── utf.mat /.ci/ci.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Do the Gradle build 4 | ./gradlew build || exit 1 5 | 6 | if [ "$TRAVIS_REPO_SLUG" == "diffplug/matfilerw" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_BRANCH" == "master" ]; then 7 | # Publish the artifacts 8 | ./gradlew publish || exit 1 9 | # Push the javadoc 10 | ./gradlew publishGhPages || exit 1 11 | fi 12 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # mac stuff 3 | *.DS_Store 4 | 5 | # gradle stuff 6 | .gradle/ 7 | build/ 8 | 9 | # Eclipse stuff 10 | .project 11 | .classpath 12 | .settings/ 13 | bin/ 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | script: "./.ci/ci.sh" 5 | before_cache: 6 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 7 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ 8 | cache: 9 | directories: 10 | - $HOME/.gradle/caches/ 11 | - $HOME/.gradle/wrapper/ 12 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | # MatFileRW releases 2 | 3 | ### Version 3.2.0-SNAPSHOT - TBD ([javadoc](http://diffplug.github.io/matfilerw/javadoc/snapshot/), [snapshot](https://oss.sonatype.org/content/repositories/snapshots/com/diffplug/matsim/matfilerw/)) 4 | 5 | ### Version 3.1.1 - December 28th 2018 ([javadoc](http://diffplug.github.io/matfilerw/javadoc/3.1.1/), [jcenter](https://bintray.com/diffplug/opensource/matfilerw/3.1.1/view)) 6 | 7 | * Fixed MatFileReader.read(File file) to allow multiple calls(see [#20](https://github.com/diffplug/matfilerw/issues/20)). 8 | 9 | ### Version 3.1.0 - November 13th 2018 ([javadoc](http://diffplug.github.io/matfilerw/javadoc/3.1.0/), [jcenter](https://bintray.com/diffplug/opensource/matfilerw/3.1.0/view)) 10 | 11 | * Added support for Jigsaw and Java 9+ (see [#16](https://github.com/diffplug/matfilerw/issues/16)). 12 | 13 | ### Version 3.0.1 - June 28th 2017 ([javadoc](http://diffplug.github.io/matfilerw/javadoc/3.0.1/), [jcenter](https://bintray.com/diffplug/opensource/matfilerw/3.0.1/view)) 14 | 15 | * Fixed second-level MCOS property dereferencing (see [#13](https://github.com/diffplug/matfilerw/issues/13)). 16 | 17 | ### Version 3.0.0 - November 22nd 2016 ([javadoc](http://diffplug.github.io/matfilerw/javadoc/3.0.0/), [jcenter](https://bintray.com/diffplug/opensource/matfilerw/3.0.0/view)) 18 | 19 | * Fixed multidimensional array indexing (see [#10](https://github.com/diffplug/matfilerw/issues/10)). 20 | + For arrays with dimension 1 or 2, there is no change. 21 | + For arrays with dimension 3 and up, matfilerw 2.x did not order the dimensions in the column-major format used by MATLAB. In 3.x forward, matfilerw uses the same column-major format as MATLAB. 22 | * `getImaginary` will always return zero for real arrays. 23 | 24 | ### Version 2.3.0 - August 18th 2016 ([javadoc](http://diffplug.github.io/matfilerw/javadoc/2.3.0/), [jcenter](https://bintray.com/diffplug/opensource/matfilerw/2.3.0/view)) 25 | 26 | * Fixed problem where a handle class is encoded within an MLObject. 27 | * MCOS variables can now be parsed from anywhere within the MAT-File (previously could only be a root variable). 28 | * Arrays of structs and fields are now enforced to have their fields be in a consistent order element to element. 29 | 30 | ### Version 2.2.0 - February 9th 2016 ([javadoc](http://diffplug.github.io/matfilerw/javadoc/2.2.0/), [jcenter](https://bintray.com/diffplug/opensource/matfilerw/2.2.0/view)) 31 | 32 | * Added `MatFile.readFull(ByteBuffer buf, MatFileType type)` 33 | * Added `MLArray.getIndex(int...)` and `MLNumericArray.set(T value, int...)` and `T get(int...)` for N-dimensional indices. 34 | * Fixed the JRE6 download in the build file. 35 | 36 | ### Version 2.1.0 - December 10th 2015 ([javadoc](http://diffplug.github.io/matfilerw/javadoc/2.1.0/), [jcenter](https://bintray.com/diffplug/opensource/matfilerw/2.1.0/view)) 37 | 38 | * Fixed support for reading UTF fields (closes [#2](https://github.com/diffplug/matfilerw/issues/2)) 39 | 40 | ### Version 2.0.0 - October 25th 2015 ([javadoc](http://diffplug.github.io/matfilerw/javadoc/2.0.0/), [jcenter](https://bintray.com/diffplug/opensource/matfilerw/2.0.0/view)) 41 | 42 | * Incorporated all changes from `codesourcery/JMatIO`. 43 | + Adds support for MCOS Objects. 44 | + Adds a Simulink decoder for reading files from Simulink MDL files. 45 | + Improved performance. 46 | * `MLObject` and `MLStructure` now share `MLStructureObjectBase` as a base class. This caused a small breaking change to `MLObject`s API. 47 | * `MatFileHeader` now wraps up the whole endianness mess, which also required a small breaking change. 48 | 49 | ### Version 2.0.0.TRANSITION - October 25th 2015 ([javadoc](http://diffplug.github.io/matfilerw/javadoc/2.0.TRANSITION/), [jcenter](https://bintray.com/diffplug/opensource/matfilerw/2.0.TRANSITION/view)) 50 | 51 | Only pertinent for people who are migrating from a JMatIO fork whose packages were renamed to `ca.mjdsystems.jmatio`. 52 | 53 | * `ca.mjdsystems.jmatio` code is included umodified, but marked as deprecated. 54 | * `com.jmatio` code is identitical to `2.0.0`. 55 | 56 | ### Version 1.3.1 - October 16th 2015 ([javadoc](http://diffplug.github.io/matfilerw/javadoc/1.3.1/), [jcenter](https://bintray.com/diffplug/opensource/matfilerw/1.3.1/view)) 57 | 58 | * Corrected the license in the maven metadata. 59 | 60 | ### Version 1.3.0 - October 16th 2015 ([javadoc](http://diffplug.github.io/matfilerw/javadoc/1.3.0/), [jcenter](https://bintray.com/diffplug/opensource/matfilerw/1.3.0/view)) 61 | 62 | * OSGi header now imports its own packages, as recommended by OSGi gurus. 63 | 64 | ### Version 1.2.0 - October 15th 2015 ([javadoc](http://diffplug.github.io/matfilerw/javadoc/1.2.0/), [jcenter](https://bintray.com/diffplug/opensource/matfilerw/1.2.0/view)) 65 | 66 | * Now available on Maven Central! 67 | * Added a sanity check to `MLNumericArray.contentToString()`. 68 | * `MatFileHeader.DEFAULT_VERSION` is now public. 69 | * Added `MatFile`, a simpler API for parsing from `MatFileReader`. 70 | * Added support for unsigned 16-bit ints. 71 | * Parsing Java objects is now more robust. 72 | * Fixed some inconsistent `equals()` and `hashCode()` implementations. 73 | * Various minor performance improvements (thanks to FindBugs). 74 | 75 | ## Versions up to 1.1.0 are from the original author's [SourceForge](http://sourceforge.net/projects/jmatio/) and [GitHub](https://github.com/gradusnikov/jmatio) pages. 76 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at community@diffplug.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to MatFileRW 2 | 3 | Pull requests are welcome, preferably against `master`. 4 | 5 | Every successful Travis CI build on branch `master` is automatically published to [`https://oss.sonatype.org/content/repositories/snapshots`](https://oss.sonatype.org/content/repositories/snapshots/com/diffplug/), and its javadoc are published [here](http://diffplug.github.io/jmatio/javadoc/snapshot/). 6 | 7 | ## Build instructions 8 | 9 | It's a bog-standard gradle build. 10 | 11 | `gradlew eclipse` 12 | * creates an Eclipse project file for you. 13 | 14 | `gradlew build` 15 | * builds the jar 16 | * runs FindBugs 17 | * checks the formatting 18 | * runs the tests 19 | 20 | If you're getting style warnings, `gradlew spotlessApply` will apply anything necessary to fix formatting. For more info on the formatter, check out [spotless](https://github.com/diffplug/spotless). 21 | 22 | ## License 23 | 24 | By contributing your code, you agree to license your contribution under the terms of the New BSD license as such: 25 | 26 | ``` 27 | All code up to tags/original: 28 | Copyright (c) 2006, Wojciech Gradkowski 29 | All rights reserved. 30 | 31 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 32 | following conditions are met: 33 | - Redistributions of source code must retain the above copyright notice, this list of conditions and the following 34 | disclaimer. 35 | - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 36 | following disclaimer in the documentation and/or other materials provided with the distribution. 37 | - Neither the name of JMatIO nor the names of its contributors may be used to endorse or promote products 38 | derived from this software without specific prior written permission. 39 | 40 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 41 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 42 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 44 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 45 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 46 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 47 | 48 | All code after tags/original: 49 | Copyright (c) 2015, DiffPlug 50 | All rights reserved. 51 | 52 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 53 | following conditions are met: 54 | - Redistributions of source code must retain the above copyright notice, this list of conditions and the following 55 | disclaimer. 56 | - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 57 | following disclaimer in the documentation and/or other materials provided with the distribution. 58 | - Neither the name of MatFileRW nor the names of its contributors may be used to endorse or promote products 59 | derived from this software without specific prior written permission. 60 | 61 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 62 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 63 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 64 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 65 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 66 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 67 | ``` 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | All code up to tags/original: 2 | Copyright (c) 2006, Wojciech Gradkowski 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 6 | following conditions are met: 7 | - Redistributions of source code must retain the above copyright notice, this list of conditions and the following 8 | disclaimer. 9 | - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 10 | following disclaimer in the documentation and/or other materials provided with the distribution. 11 | - Neither the name of JMatIO nor the names of its contributors may be used to endorse or promote products 12 | derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 15 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 17 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 18 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 19 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 20 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 21 | 22 | All code after tags/original: 23 | Copyright (c) 2015, DiffPlug 24 | All rights reserved. 25 | 26 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 27 | following conditions are met: 28 | - Redistributions of source code must retain the above copyright notice, this list of conditions and the following 29 | disclaimer. 30 | - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 31 | following disclaimer in the documentation and/or other materials provided with the distribution. 32 | - Neither the name of MatFileRW nor the names of its contributors may be used to endorse or promote products 33 | derived from this software without specific prior written permission. 34 | 35 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 36 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 37 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 38 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 39 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 40 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 41 | -------------------------------------------------------------------------------- /META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Bundle-Description: MatFileRW - Read and write .mat files 3 | Bundle-DocURL: https://github.com/diffplug/matfilerw 4 | Bundle-License: https://github.com/diffplug/matfilerw/blob/v3.1.0-SNAP 5 | SHOT/LICENSE 6 | Bundle-ManifestVersion: 2 7 | Bundle-SymbolicName: com.diffplug.matsim.matfilerw 8 | Bundle-Vendor: DiffPlug 9 | Bundle-Version: 3.1.0.I201706282450 10 | Export-Package: com.jmatio.common;version="3.1.0",com.jmatio.common.ut 11 | il;uses:="com.jmatio.types";version="3.1.0",com.jmatio.io;uses:="com. 12 | jmatio.types";version="3.1.0",com.jmatio.io.stream;uses:="com.jmatio. 13 | types";version="3.1.0",com.jmatio.types;uses:="com.jmatio.common";ver 14 | sion="3.1.0" 15 | Import-Package: sun.misc;resolution:=optional,com.jmatio.common,com.jm 16 | atio.io.stream,com.jmatio.types 17 | Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.6))" 18 | -------------------------------------------------------------------------------- /MatlabClasses/HandleClass.m: -------------------------------------------------------------------------------- 1 | % http://stackoverflow.com/questions/36025747/matlab-documentation-on-handle-variables-and-mat-files 2 | classdef HandleClass < handle 3 | properties 4 | myPropA 5 | end % properties 6 | end % classdef 7 | -------------------------------------------------------------------------------- /MatlabClasses/OtherClass.m: -------------------------------------------------------------------------------- 1 | % http://stackoverflow.com/questions/36025747/matlab-documentation-on-handle-variables-and-mat-files 2 | classdef OtherClass 3 | properties 4 | myObjA 5 | end % properties 6 | end % classdef 7 | -------------------------------------------------------------------------------- /MatlabClasses/SimpleEmpty.m: -------------------------------------------------------------------------------- 1 | classdef SimpleEmpty 2 | %SIMPLEEMPTY A simple empty class definition. 3 | 4 | properties 5 | end 6 | 7 | methods 8 | end 9 | 10 | end 11 | -------------------------------------------------------------------------------- /MatlabClasses/SimpleSingleText.m: -------------------------------------------------------------------------------- 1 | classdef SimpleSingleText 2 | %SIMPLESINGLETEXT Summary of this class goes here 3 | % Detailed explanation goes here 4 | 5 | properties 6 | test_text = 'Default text' 7 | end 8 | 9 | methods 10 | end 11 | 12 | end 13 | -------------------------------------------------------------------------------- /MatlabClasses/TestHandleClass.m: -------------------------------------------------------------------------------- 1 | % http://stackoverflow.com/questions/36025747/matlab-documentation-on-handle-variables-and-mat-files 2 | 3 | %% create and save the objects 4 | % Create 2 object variables. 2nd 5 | % one has a property that refers to 6 | % same object as the first one 7 | objA = HandleClass; 8 | objA.myPropA = 5; 9 | objB = OtherClass; 10 | objB.myObjA = objA; 11 | objC = HandleClass; 12 | objC.myPropA = objA; 13 | 14 | save('../src/test/resources/handles.mat', 'objA', 'objB', 'objC'); 15 | 16 | %% clear and load them back 17 | clear 18 | load('../src/test/resources/handles.mat') 19 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | After creating the PR, please add a commit that adds a bullet-point under the `-SNAPSHOT` section of [CHANGES.md](https://github.com/diffplug/matfilerw/blob/master/CHANGES.md) that includes: 2 | 3 | - [ ] a summary of the change 4 | - [ ] a link to the newly created PR 5 | 6 | This makes it easier for the maintainers to quickly release your changes. 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## MatFileRW is not abandoned, but we recommend migrating to [HebiRobotics/MFL](https://github.com/HebiRobotics/MFL) 2 | 3 | MatFileRW will continue to accept bug reports and PRs. However, we recommend starting new projects with [HebiRobotics/MFL](https://github.com/HebiRobotics/MFL) because it: 4 | 5 | - has every testcase from MatFileRW and more 6 | - has a cleaner and more modern codebase 7 | - supports concurrent compression and decompression 8 | - is designed for interoperability with native-Java matrix manipulation 9 | - has optional [EJML](https://ejml.org) integration 10 | 11 | Besides the effort to learn the new API, there are no downsides and quite a few upsides. Migrating a project is a big job, so we will continue to accept bug reports and PR's for MatFileRW to support those who don't choose to migrate. 12 | 13 | # MatFileRW: Read and write MATLAB MAT-files from Java 14 | 15 | 26 | [![Maven artifact](https://img.shields.io/badge/mavenCentral-com.diffplug.matsim%3Amatfilerw-blue.svg)](https://bintray.com/diffplug/opensource/matfilerw/view) 27 | [![Latest version](https://img.shields.io/badge/latest-3.1.1-blue.svg)](https://github.com/diffplug/matfilerw/releases/latest) 28 | [![Javadoc](https://img.shields.io/badge/javadoc-OK-blue.svg)](https://diffplug.github.io/matfilerw/javadoc/3.1.1/) 29 | [![License Apache](https://img.shields.io/badge/license-BSD-blue.svg)](https://tldrlegal.com/license/bsd-3-clause-license-(revised)) 30 | 31 | [![Changelog](https://img.shields.io/badge/changelog-3.2.0--SNAPSHOT-brightgreen.svg)](CHANGES.md) 32 | [![Travis CI](https://travis-ci.org/diffplug/matfilerw.svg?branch=master)](https://travis-ci.org/diffplug/matfilerw) 33 | 34 | 35 | MatFileRW is a library which allows reading and writing MAT files. Have a look at [MatIOTest.java](https://github.com/diffplug/matfilerw/blob/master/src/test/java/com/jmatio/io/MatIOTest.java) to see each part in use. 36 | 37 | As far as compatibility, the TL;DR is that it will work with any MAT-File with default settings. The dirty details are that this library works with `v6` and `v7`, but not `v4` or `v7.3`. 38 | 39 | * v4 is the default format before R8 40 | * v6 is the default format from R8 to R13 41 | * v7 is the default format from R14 to present (every R20XXX release) 42 | * MATLAB does not export to v7.3 by default. 43 | * The [Mathworks website](http://www.mathworks.com/help/matlab/import_export/mat-file-versions.html?refresh=true) has more details. 44 | 45 | ## codemercenary/jmatio and ca.mjdsystems.jmatio 46 | 47 | Since JMatIO wasn't updated for a while, lots of people made forks. One of the most prominent was Jason Lokerson's, hosted on GitHub as codemercenary/JMatIO. It included several improvements, but all the packages were renamed to `ca.mjdsystems.jmatio`. Starting with 2.0.0, all of the improvements from MatFileRW and `ca.mjdsystems.jmatio` have been merged into the `com.jmatio` packages. 48 | 49 | If you are a user of the `ca.mjdsystems` packages, you should download `com.diffplug.matsim:matfilerw:2.0.0.TRANSITION` from mavenCentral. This contains the `ca.mjdsystems.jmatio` packages unchanged, but marked as deprecated. After you have removed all dependencies on the `ca.mjdsystems.jmatio` packages, you will be able to use the regular `2.0.0` version, and its descendants. 50 | 51 | ## Acknowledgements 52 | 53 | This project is forked from the JMatIO project originally maintained on [SourceForge](http://sourceforge.net/projects/jmatio/), and now maintained on [GitHub](https://github.com/gradusnikov/jmatio). The name was changed to ensure that we don't infringe the original project's license, but we did not change the package names, so this project is binary compatible with the original JMatIO. We are very thankful to Wojciech Gradkowski for creating JMatIO, but this fork is in no way associated with or endorsed by any authors of the original project. 54 | 55 | We have fixed some bugs and added some features (see the [changelog](CHANGES.md)), and we will maintain this library into the future. We're happy to accept [pull requests](CONTRIBUTING.md) too! 56 | 57 | People whose commits are included in this project 58 | * Original JMatIO project credit to Wojciech Gradkowski 59 | * Thanks to Tim Ryan for [finding and fixing](https://github.com/diffplug/matfilerw/pull/9) a multidimensional indexing bug. 60 | * MLSparse improvements credit to Sina Samangooei 61 | * Reading from streams credit to Jonathan Hare 62 | * MCOS and Simulink MAT-File parsing by Matthew Dawson 63 | * Further MCOS fixes thanks to Piotr Smolinski 64 | * int32 writing by Gabriel Shubiner 65 | * ZLIP EOF Exception fix by David Williams 66 | * Integration work by Jason Lokerson 67 | * Multidimensional array indexing by Mikael Grev 68 | * AbstractIterator taken from Google's Guava 69 | 70 | Tools used by this project 71 | * Formatted by [spotless](https://github.com/diffplug/spotless), [as such](https://github.com/diffplug/matfilerw/blob/v1.3.1/build.gradle?ts=4#L129-L149). 72 | * Bugs found by [findbugs](http://findbugs.sourceforge.net/), [as such](https://github.com/diffplug/matfilerw/blob/v1.3.1/build.gradle?ts=4#L151-L175). 73 | * OSGi metadata generated by [Goomph](https://github.com/diffplug/goomph), which leverages Peter Kriens' [bnd](http://www.aqute.biz/Bnd/Bnd). 74 | * Built by [gradle](http://gradle.org/). 75 | * Tested by [junit](http://junit.org/). 76 | * Maintained by [DiffPlug](http://www.diffplug.com/). 77 | -------------------------------------------------------------------------------- /doc/matfile_format.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/doc/matfile_format.pdf -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | stable=3.1.1 2 | version=3.2.0-SNAPSHOT 3 | name=matfilerw 4 | group=com.diffplug.matsim 5 | description=MatFileRW - Read and write .mat files 6 | org=diffplug 7 | 8 | # Build requirements 9 | VER_JAVA=1.6 10 | VER_FINDBUGS=3.0.1 11 | 12 | # Testing 13 | VER_JUNIT=4.12 14 | -------------------------------------------------------------------------------- /gradle/spotless.importorder: -------------------------------------------------------------------------------- 1 | #Organize Import Order 2 | #Fri Apr 24 02:36:28 PDT 2015 3 | 4=com.diffplug 4 | 3=com 5 | 2=org 6 | 1=javax 7 | 0=java 8 | -------------------------------------------------------------------------------- /gradle/spotless.license.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Nov 12 18:45:38 PST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /matfilerw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/matfilerw.png -------------------------------------------------------------------------------- /src/main/assembly/bundle.xml: -------------------------------------------------------------------------------- 1 | 3 | bundle 4 | 5 | jar 6 | 7 | / 8 | 9 | 10 | ${project.build.directory} 11 | / 12 | 13 | ${project.build.finalName}.jar 14 | ${project.build.finalName}.jar.asc 15 | ${project.build.finalName}.pom 16 | ${project.build.finalName}.pom.asc 17 | ${project.build.finalName}-javadoc.jar 18 | ${project.build.finalName}-javadoc.jar.asc 19 | ${project.build.finalName}-sources.jar 20 | ${project.build.finalName}-sources.jar.asc 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/common/AbstractIterator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.common; 7 | 8 | import java.util.Iterator; 9 | import java.util.NoSuchElementException; 10 | 11 | /** Copied from Guava. */ 12 | abstract class AbstractIterator implements Iterator { 13 | private State state = State.NOT_READY; 14 | 15 | /** Constructor for use by subclasses. */ 16 | protected AbstractIterator() {} 17 | 18 | private enum State { 19 | /** We have computed the next element and haven't returned it yet. */ 20 | READY, 21 | 22 | /** We haven't yet computed or have already returned the element. */ 23 | NOT_READY, 24 | 25 | /** We have reached the end of the data and are finished. */ 26 | DONE, 27 | 28 | /** We've suffered an exception and are kaput. */ 29 | FAILED, 30 | } 31 | 32 | private T next; 33 | 34 | /** 35 | * Returns the next element. Note: the implementation must call {@link 36 | * #endOfData()} when there are no elements left in the iteration. Failure to 37 | * do so could result in an infinite loop. 38 | * 39 | *

The initial invocation of {@link #hasNext()} or {@link #next()} calls 40 | * this method, as does the first invocation of {@code hasNext} or {@code 41 | * next} following each successful call to {@code next}. Once the 42 | * implementation either invokes {@code endOfData} or throws an exception, 43 | * {@code computeNext} is guaranteed to never be called again. 44 | * 45 | *

If this method throws an exception, it will propagate outward to the 46 | * {@code hasNext} or {@code next} invocation that invoked this method. Any 47 | * further attempts to use the iterator will result in an {@link 48 | * IllegalStateException}. 49 | * 50 | *

The implementation of this method may not invoke the {@code hasNext}, 51 | * {@code next}, or {@link #peek()} methods on this instance; if it does, an 52 | * {@code IllegalStateException} will result. 53 | * 54 | * @return the next element if there was one. If {@code endOfData} was called 55 | * during execution, the return value will be ignored. 56 | * @throws RuntimeException if any unrecoverable error happens. This exception 57 | * will propagate outward to the {@code hasNext()}, {@code next()}, or 58 | * {@code peek()} invocation that invoked this method. Any further 59 | * attempts to use the iterator will result in an 60 | * {@link IllegalStateException}. 61 | */ 62 | protected abstract T computeNext(); 63 | 64 | /** 65 | * Implementations of {@link #computeNext} must invoke this method when 66 | * there are no elements left in the iteration. 67 | * 68 | * @return {@code null}; a convenience so your {@code computeNext} 69 | * implementation can use the simple statement {@code return endOfData();} 70 | */ 71 | protected final T endOfData() { 72 | state = State.DONE; 73 | return null; 74 | } 75 | 76 | @Override 77 | public final boolean hasNext() { 78 | if (state == State.FAILED) { 79 | throw new IllegalStateException(); 80 | } 81 | switch (state) { 82 | case DONE: 83 | return false; 84 | case READY: 85 | return true; 86 | default: 87 | } 88 | return tryToComputeNext(); 89 | } 90 | 91 | private boolean tryToComputeNext() { 92 | state = State.FAILED; // temporary pessimism 93 | next = computeNext(); 94 | if (state != State.DONE) { 95 | state = State.READY; 96 | return true; 97 | } 98 | return false; 99 | } 100 | 101 | @Override 102 | public final T next() { 103 | if (!hasNext()) { 104 | throw new NoSuchElementException(); 105 | } 106 | state = State.NOT_READY; 107 | T result = next; 108 | next = null; 109 | return result; 110 | } 111 | 112 | /** 113 | * Returns the next element in the iteration without advancing the iteration, 114 | * according to the contract of {@link PeekingIterator#peek()}. 115 | * 116 | *

Implementations of {@code AbstractIterator} that wish to expose this 117 | * functionality should implement {@code PeekingIterator}. 118 | */ 119 | public final T peek() { 120 | if (!hasNext()) { 121 | throw new NoSuchElementException(); 122 | } 123 | return next; 124 | } 125 | 126 | public final void remove() { 127 | throw new UnsupportedOperationException(); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/common/DeterministicKeyMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.common; 7 | 8 | import java.util.Collection; 9 | import java.util.Iterator; 10 | import java.util.Map; 11 | import java.util.Set; 12 | 13 | /** 14 | * A map implementation which guarantees that all of its iterators 15 | * (keySet(), values(), and entrySet()) will be in the same order 16 | * as the keyOrder set which is passed in the constructor. 17 | * 18 | * The keySet must contain all of the keys in the delegate, but it's 19 | * okay if the keySet contains more. 20 | * 21 | * Useful in MLObject and MLStruct for ensuring that arrays have 22 | * their fields in the same order. 23 | */ 24 | public class DeterministicKeyMap extends ForwardingMap { 25 | private final Set keyOrder; 26 | 27 | /** 28 | * 29 | * @param keyOrder A set which must always contain all of the keys in delegate, and may contain more. 30 | * @param delegate An underlying map. 31 | */ 32 | public DeterministicKeyMap(Set keyOrder, Map delegate) { 33 | super(delegate); 34 | this.keyOrder = keyOrder; 35 | } 36 | 37 | /** Returns the keyset of this map in the same order as keyOrder. */ 38 | @SuppressWarnings("unchecked") 39 | @Override 40 | public Set keySet() { 41 | return new DeterministicSet(delegate.keySet(), (Function) identity); 42 | } 43 | 44 | /** Returns the values of this map in the same order as keyOrder. */ 45 | @Override 46 | public Collection values() { 47 | return new DeterministicCollection(delegate.values(), new Function() { 48 | @Override 49 | public V apply(K input) { 50 | return delegate.get(input); 51 | } 52 | }); 53 | } 54 | 55 | /** Returns the entries of this map in the same order as keyOrder. */ 56 | @Override 57 | public Set> entrySet() { 58 | return new DeterministicSet>(delegate.entrySet(), new Function>() { 59 | @Override 60 | public Map.Entry apply(final K key) { 61 | return new Map.Entry() { 62 | @Override 63 | public K getKey() { 64 | return key; 65 | } 66 | 67 | @Override 68 | public V getValue() { 69 | return delegate.get(key); 70 | } 71 | 72 | @Override 73 | public V setValue(V value) { 74 | return delegate.put(key, value); 75 | } 76 | }; 77 | } 78 | }); 79 | } 80 | 81 | @Override 82 | public boolean equals(Object other) { 83 | return super.equals(other); 84 | } 85 | 86 | @Override 87 | public int hashCode() { 88 | return super.hashCode(); 89 | } 90 | 91 | /** Java didn't find functional programming until Java 8. */ 92 | static interface Function { 93 | R apply(T input); 94 | } 95 | 96 | static final Function identity = new Function() { 97 | @Override 98 | public Object apply(Object input) { 99 | return input; 100 | } 101 | }; 102 | 103 | /** DeterministicCollection which guarantees a Set delegate. */ 104 | class DeterministicSet extends DeterministicCollection implements Set { 105 | DeterministicSet(Set delegate, Function keyToValue) { 106 | super(delegate, keyToValue); 107 | } 108 | } 109 | 110 | /** A collection which iterates over the key set, transformed into values using the given function. */ 111 | class DeterministicCollection extends ForwardingCollection { 112 | Function keyToValue; 113 | 114 | DeterministicCollection(Collection delegate, Function keyToValue) { 115 | super(delegate); 116 | this.keyToValue = keyToValue; 117 | } 118 | 119 | @Override 120 | public Iterator iterator() { 121 | final Iterator iterByKey = keyOrder.iterator(); 122 | return new AbstractIterator() { 123 | @Override 124 | protected T computeNext() { 125 | while (iterByKey.hasNext()) { 126 | K nextKey = iterByKey.next(); 127 | T value = keyToValue.apply(nextKey); 128 | if (delegate.contains(value)) { 129 | return value; 130 | } 131 | } 132 | return endOfData(); 133 | } 134 | }; 135 | } 136 | 137 | @Override 138 | public boolean equals(Object other) { 139 | return super.equals(other); 140 | } 141 | 142 | @Override 143 | public int hashCode() { 144 | return super.hashCode(); 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/common/ForwardingCollection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.common; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Collection; 10 | import java.util.Iterator; 11 | 12 | /** 13 | * A Collection which forwards all calls to a delegate collection, 14 | * except for toArray(), which are overridden to reflect any changes 15 | * in the iterator() method. 16 | * 17 | * Used to implement {@link DeterministicKeyMap}. 18 | */ 19 | class ForwardingCollection implements Collection { 20 | protected final Collection delegate; 21 | 22 | protected ForwardingCollection(Collection delegate) { 23 | this.delegate = delegate; 24 | } 25 | 26 | @Override 27 | public Iterator iterator() { 28 | return delegate.iterator(); 29 | } 30 | 31 | @Override 32 | public Object[] toArray() { 33 | Object[] result = new Object[this.size()]; 34 | return toArray(result); 35 | } 36 | 37 | @Override 38 | public R[] toArray(R[] a) { 39 | ArrayList result = new ArrayList(size()); 40 | Iterator iter = iterator(); 41 | while (iter.hasNext()) { 42 | result.add(iter.next()); 43 | } 44 | return result.toArray(a); 45 | } 46 | 47 | @Override 48 | public int size() { 49 | return delegate.size(); 50 | } 51 | 52 | @Override 53 | public boolean isEmpty() { 54 | return delegate.isEmpty(); 55 | } 56 | 57 | @Override 58 | public boolean contains(Object o) { 59 | return delegate.contains(o); 60 | } 61 | 62 | @Override 63 | public boolean add(T e) { 64 | return delegate.add(e); 65 | } 66 | 67 | @Override 68 | public boolean remove(Object o) { 69 | return delegate.remove(o); 70 | } 71 | 72 | @Override 73 | public boolean containsAll(Collection c) { 74 | return delegate.containsAll(c); 75 | } 76 | 77 | @Override 78 | public boolean addAll(Collection c) { 79 | return delegate.addAll(c); 80 | } 81 | 82 | @Override 83 | public boolean removeAll(Collection c) { 84 | return delegate.removeAll(c); 85 | } 86 | 87 | @Override 88 | public boolean retainAll(Collection c) { 89 | return delegate.retainAll(c); 90 | } 91 | 92 | @Override 93 | public void clear() { 94 | delegate.clear(); 95 | } 96 | 97 | @Override 98 | public int hashCode() { 99 | return delegate.hashCode(); 100 | } 101 | 102 | @Override 103 | public boolean equals(Object other) { 104 | return delegate.equals(other); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/common/ForwardingMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.common; 7 | 8 | import java.util.Collection; 9 | import java.util.Map; 10 | import java.util.Set; 11 | 12 | /** A Map which forwards all of its method calls to a delegate map. Used to implement {@link DeterministicKeyMap}. */ 13 | class ForwardingMap implements Map { 14 | protected final Map delegate; 15 | 16 | protected ForwardingMap(Map delegate) { 17 | this.delegate = delegate; 18 | } 19 | 20 | @Override 21 | public int size() { 22 | return delegate.size(); 23 | } 24 | 25 | @Override 26 | public boolean isEmpty() { 27 | return delegate.isEmpty(); 28 | } 29 | 30 | @Override 31 | public boolean containsKey(Object key) { 32 | return delegate.containsKey(key); 33 | } 34 | 35 | @Override 36 | public boolean containsValue(Object value) { 37 | return delegate.containsValue(value); 38 | } 39 | 40 | @Override 41 | public V get(Object key) { 42 | return delegate.get(key); 43 | } 44 | 45 | @Override 46 | public V put(K key, V value) { 47 | return delegate.put(key, value); 48 | } 49 | 50 | @Override 51 | public V remove(Object key) { 52 | return delegate.remove(key); 53 | } 54 | 55 | @Override 56 | public void putAll(Map m) { 57 | delegate.putAll(m); 58 | } 59 | 60 | @Override 61 | public void clear() { 62 | delegate.clear(); 63 | } 64 | 65 | @Override 66 | public Set keySet() { 67 | return delegate.keySet(); 68 | } 69 | 70 | @Override 71 | public Collection values() { 72 | return delegate.values(); 73 | } 74 | 75 | @Override 76 | public Set> entrySet() { 77 | return delegate.entrySet(); 78 | } 79 | 80 | @Override 81 | public int hashCode() { 82 | return delegate.hashCode(); 83 | } 84 | 85 | @Override 86 | public boolean equals(Object other) { 87 | return delegate.equals(other); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/common/MatDataTypes.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.common; 7 | 8 | /** 9 | * MAT-file data types 10 | * 11 | * @author Wojciech Gradkowski 12 | */ 13 | public class MatDataTypes { 14 | public static final String CHARSET = "UTF-8"; 15 | 16 | /* MAT-File Data Types */ 17 | public static final int miUNKNOWN = 0; 18 | public static final int miINT8 = 1; 19 | public static final int miUINT8 = 2; 20 | public static final int miINT16 = 3; 21 | public static final int miUINT16 = 4; 22 | public static final int miINT32 = 5; 23 | public static final int miUINT32 = 6; 24 | public static final int miSINGLE = 7; 25 | public static final int miDOUBLE = 9; 26 | public static final int miINT64 = 12; 27 | public static final int miUINT64 = 13; 28 | public static final int miMATRIX = 14; 29 | public static final int miCOMPRESSED = 15; 30 | public static final int miUTF8 = 16; 31 | public static final int miUTF16 = 17; 32 | public static final int miUTF32 = 18; 33 | 34 | public static final int miSIZE_INT64 = 8; 35 | public static final int miSIZE_INT32 = 4; 36 | public static final int miSIZE_INT16 = 2; 37 | public static final int miSIZE_INT8 = 1; 38 | public static final int miSIZE_UINT64 = 8; 39 | public static final int miSIZE_UINT32 = 4; 40 | public static final int miSIZE_UINT16 = 2; 41 | public static final int miSIZE_UINT8 = 1; 42 | public static final int miSIZE_DOUBLE = 8; 43 | public static final int miSIZE_CHAR = 1; 44 | 45 | /** 46 | * Return number of bytes for given type. 47 | * 48 | * @param type - MatDataTypes 49 | * @return 50 | */ 51 | public static int sizeOf(int type) { 52 | switch (type) { 53 | case MatDataTypes.miINT8: 54 | return miSIZE_INT8; 55 | case MatDataTypes.miUINT8: 56 | return miSIZE_UINT8; 57 | case MatDataTypes.miINT16: 58 | return miSIZE_INT16; 59 | case MatDataTypes.miUINT16: 60 | return miSIZE_UINT16; 61 | case MatDataTypes.miINT32: 62 | return miSIZE_INT32; 63 | case MatDataTypes.miUINT32: 64 | return miSIZE_UINT32; 65 | case MatDataTypes.miINT64: 66 | return miSIZE_INT64; 67 | case MatDataTypes.miUINT64: 68 | return miSIZE_UINT64; 69 | case MatDataTypes.miDOUBLE: 70 | return miSIZE_DOUBLE; 71 | default: 72 | return 1; 73 | } 74 | } 75 | 76 | /** 77 | * Get String representation of a data type 78 | * 79 | * @param type - data type 80 | * @return - String representation 81 | */ 82 | public static String typeToString(int type) { 83 | String s; 84 | switch (type) { 85 | case MatDataTypes.miUNKNOWN: 86 | s = "unknown"; 87 | break; 88 | case MatDataTypes.miINT8: 89 | s = "int8"; 90 | break; 91 | case MatDataTypes.miUINT8: 92 | s = "uint8"; 93 | break; 94 | case MatDataTypes.miINT16: 95 | s = "int16"; 96 | break; 97 | case MatDataTypes.miUINT16: 98 | s = "uint16"; 99 | break; 100 | case MatDataTypes.miINT32: 101 | s = "int32"; 102 | break; 103 | case MatDataTypes.miUINT32: 104 | s = "uint32"; 105 | break; 106 | case MatDataTypes.miSINGLE: 107 | s = "single"; 108 | break; 109 | case MatDataTypes.miDOUBLE: 110 | s = "double"; 111 | break; 112 | case MatDataTypes.miINT64: 113 | s = "int64"; 114 | break; 115 | case MatDataTypes.miUINT64: 116 | s = "uint64"; 117 | break; 118 | case MatDataTypes.miMATRIX: 119 | s = "matrix"; 120 | break; 121 | case MatDataTypes.miCOMPRESSED: 122 | s = "compressed"; 123 | break; 124 | case MatDataTypes.miUTF8: 125 | s = "uft8"; 126 | break; 127 | case MatDataTypes.miUTF16: 128 | s = "utf16"; 129 | break; 130 | case MatDataTypes.miUTF32: 131 | s = "utf32"; 132 | break; 133 | default: 134 | s = "unknown"; 135 | } 136 | return s; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/common/util/MLArrayQuery.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.common.util; 7 | 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | import com.jmatio.types.MLArray; 12 | import com.jmatio.types.MLCell; 13 | import com.jmatio.types.MLChar; 14 | import com.jmatio.types.MLNumericArray; 15 | import com.jmatio.types.MLObject; 16 | import com.jmatio.types.MLStructure; 17 | 18 | /** 19 | * The JMatIO query parser. Allows to use Matlab-like syntax to access {@link MLArray} objects. 20 | *

21 | * 22 | * @author wgradkowski 23 | * 24 | */ 25 | public class MLArrayQuery { 26 | private String queryString; 27 | 28 | private static final String regexp = "([a-zA-Z0-9]+)(\\(([0-9]+|:)(,([0-9:]+|:))?\\))?\\.?"; 29 | private static final Pattern pat = Pattern.compile(regexp); 30 | 31 | public MLArrayQuery(String queryString) { 32 | if (!Pattern.matches("^(" + regexp + ")+$", queryString)) { 33 | throw new IllegalArgumentException(); 34 | } 35 | 36 | this.queryString = queryString; 37 | } 38 | 39 | /** 40 | * 41 | * 42 | * @param array 43 | * @param query 44 | * @return 45 | */ 46 | public static Object q(MLArray array, String query) { 47 | MLArrayQuery q = new MLArrayQuery(query); 48 | 49 | return q.query(array); 50 | } 51 | 52 | /** 53 | * Parses the query string and returns the object it refers to. 54 | * 55 | * @param array 56 | * source {@link MLArray} 57 | * @return query result 58 | */ 59 | public Object query(MLArray array) { 60 | Matcher mat = pat.matcher(queryString); 61 | 62 | MLArray current = null; 63 | 64 | int prevM = 0; 65 | int prevN = 0; 66 | 67 | while (mat.find()) { 68 | String name = mat.group(1); 69 | String rangeM = mat.group(3); 70 | String rangeN = mat.group(5); 71 | 72 | int m = rangeM != null ? Integer.parseInt(rangeM) - 1 : -1; 73 | int n = rangeN != null ? Integer.parseInt(rangeN) - 1 : -1; 74 | 75 | if (current == null) { 76 | current = array; 77 | 78 | if (!current.getName().equals(name) && !current.getName().equals(MLArray.DEFAULT_NAME)) { 79 | throw new RuntimeException("No such array or field <" + name + "> in <" + current.getName() + ">"); 80 | } 81 | 82 | prevM = m; 83 | prevN = n; 84 | 85 | continue; 86 | } 87 | 88 | int type = current.getType(); 89 | 90 | switch (type) { 91 | case MLArray.mxOBJECT_CLASS: { 92 | MLObject object = cast(current, MLObject.class); 93 | MLArray field = object.getField(name); 94 | if (field == null) { 95 | throw new RuntimeException("no such field: " + name); 96 | } 97 | current = field; 98 | } 99 | break; 100 | case MLArray.mxSTRUCT_CLASS: { 101 | MLStructure struct = cast(current, MLStructure.class); 102 | MLArray field = struct.getField(name, prevM > 0 ? prevM : 0, prevN > 0 ? prevN : 0); 103 | if (field == null) { 104 | throw new RuntimeException("no such field: " + name); 105 | } 106 | current = field; 107 | } 108 | break; 109 | case MLArray.mxCELL_CLASS: { 110 | MLCell mlcell = cast(current, MLCell.class); 111 | if (m > -1 && n > -1) { 112 | current = mlcell.get(m, n); 113 | } else if (m > -1) { 114 | current = mlcell.get(m); 115 | } else { 116 | throw new RuntimeException(); 117 | } 118 | } 119 | break; 120 | default: 121 | } 122 | prevM = m; 123 | prevN = n; 124 | } 125 | 126 | return getContent(current, prevM, prevN); 127 | } 128 | 129 | /** 130 | * Returns the content of the field/cell/object. 131 | * 132 | * @param array 133 | * the parent structure/cell 134 | * @param m 135 | * column or -1 136 | * @param n 137 | * row or -1 138 | * @return if both m and n are -1, returns {@link MLArray}, if n is -1, returns 139 | * content under index m, if both m and n are not-negative, returns 140 | * content of (m,n) 141 | */ 142 | public Object getContent(MLArray array, int m, int n) { 143 | int type = array.getType(); 144 | 145 | Object result = null; 146 | 147 | switch (type) { 148 | case MLArray.mxINT8_CLASS: 149 | case MLArray.mxINT16_CLASS: 150 | case MLArray.mxINT32_CLASS: 151 | case MLArray.mxINT64_CLASS: 152 | case MLArray.mxUINT8_CLASS: 153 | case MLArray.mxUINT16_CLASS: 154 | case MLArray.mxUINT32_CLASS: 155 | case MLArray.mxUINT64_CLASS: 156 | case MLArray.mxSINGLE_CLASS: 157 | case MLArray.mxDOUBLE_CLASS: 158 | MLNumericArray numeric = cast(array, MLNumericArray.class); 159 | if (m > -1 && n > -1) { 160 | result = numeric.get(m, n); 161 | } else if (m > -1) { 162 | result = numeric.get(m); 163 | } else { 164 | result = array; 165 | } 166 | break; 167 | case MLArray.mxCHAR_CLASS: 168 | MLChar mlchar = cast(array, MLChar.class); 169 | if (m > -1 && n > -1) { 170 | result = mlchar.getChar(m, n); 171 | } else if (m > -1) { 172 | result = mlchar.getString(m); 173 | } else { 174 | result = mlchar; 175 | } 176 | break; 177 | case MLArray.mxCELL_CLASS: 178 | MLCell mlcell = cast(array, MLCell.class); 179 | if (m > -1 && n > -1) { 180 | result = getContent(mlcell.get(m, n), 0, -1); 181 | } else if (m > -1) { 182 | result = getContent(mlcell.get(m), 0, -1); 183 | } else { 184 | result = getContent(mlcell.get(0), -1, -1); 185 | } 186 | break; 187 | default: 188 | result = array; 189 | } 190 | return result; 191 | } 192 | 193 | /** Performs a checked cast to keep FindBugs happy. */ 194 | @SuppressWarnings("unchecked") 195 | private static T cast(Object o, Class clazz) { 196 | if (o.getClass().isAssignableFrom(clazz)) { 197 | return (T) o; 198 | } else { 199 | throw new ClassCastException(o.getClass().toString()); 200 | } 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/MLObjectPlaceholder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io; 7 | 8 | import com.jmatio.types.MLObject; 9 | 10 | /** 11 | * 12 | * @author Matthew Dawson 13 | */ 14 | class MLObjectPlaceholder extends MLObject { 15 | MLObjectPlaceholder(String name, String className, int[][] information) { 16 | super(name, className, new int[]{information[2][0], information[3][0]}, -1); 17 | 18 | this.objectIds = new int[information.length - 5]; 19 | for (int i = 0; i < objectIds.length; ++i) { 20 | objectIds[i] = information[i + 4][0]; 21 | } 22 | this.classId = information[information.length - 1][0]; 23 | } 24 | 25 | final int[] objectIds; 26 | final int classId; 27 | 28 | void setTarget(MLObject obj) { 29 | copyFrom(obj); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/MatFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io; 7 | 8 | import java.io.IOException; 9 | import java.io.RandomAccessFile; 10 | import java.nio.ByteBuffer; 11 | import java.util.Map; 12 | 13 | import com.jmatio.types.MLArray; 14 | 15 | /** 16 | * MatFileReader's API is vague. Do you pass a file in the constructor 17 | * or the read method? It also limits your ability to partially parse 18 | * a section of code, such as the case where you have a MAT-file without 19 | * a header 20 | *

21 | * MatFile is a value class which presents a simplified API for parsing either a 22 | * ByteBuffer or a RandomAccessFile. 23 | */ 24 | public class MatFile { 25 | private final MatFileHeader header; 26 | private final Map content; 27 | 28 | public MatFile(MatFileHeader header, Map content) { 29 | this.header = header; 30 | this.content = content; 31 | } 32 | 33 | public MatFileHeader getHeader() { 34 | return header; 35 | } 36 | 37 | public Map getContent() { 38 | return content; 39 | } 40 | 41 | /** Reads a bare set of bytes. */ 42 | public static Map readBare(MatFileHeader header, ByteBuffer buffer) throws IOException { 43 | MatFileReader reader = new MatFileReader(); 44 | reader.matFileHeader = header; 45 | buffer.order(header.getByteOrder()); 46 | reader.readData(buffer); 47 | return reader.data; 48 | } 49 | 50 | /** Reads a full set of bytes (including the header). */ 51 | public static MatFile readFull(ByteBuffer buf) throws IOException { 52 | return readFull(buf, MatFileType.Regular); 53 | } 54 | 55 | /** Reads a full set of bytes (including the header). */ 56 | public static MatFile readFull(ByteBuffer buf, MatFileType type) throws IOException { 57 | MatFileReader reader = new MatFileReader(type); 58 | reader.readHeader(buf); 59 | while (buf.remaining() > 0) { 60 | reader.readData(buf); 61 | } 62 | return new MatFile(reader.getMatFileHeader(), reader.getContent()); 63 | } 64 | 65 | /** Reads a full set of bytes (including the header). */ 66 | public static MatFile readFull(RandomAccessFile file) throws IOException { 67 | MatFileReader reader = new MatFileReader(); 68 | reader.read(file, new MatFileFilter(), MatFileReader.HEAP_BYTE_BUFFER); 69 | return new MatFile(reader.getMatFileHeader(), reader.getContent()); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/MatFileFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io; 7 | 8 | import java.util.HashSet; 9 | import java.util.Set; 10 | 11 | /** 12 | * File filter. 13 | * 14 | * This class is used to tell MatFileReader which matrices 15 | * should be processed. This is useful when operating on big MAT-files, 16 | * when there's no need to load all arrays into memory. 17 | * 18 | * Usage: 19 | *


20 |  * //create new filter instance
21 |  * MatFileFilter filter = new MatFileFilter();
22 |  * //add a needle
23 |  * filter.addArrayName( "your_array_name" );
24 |  * 
25 |  * //read array form file (haystack) looking _only_ for pecified array (needle)
26 |  * MatFileReader mfr = new MatFileReader( fileName, filter );
27 |  * 
28 | * 29 | * @see com.jmatio.io.MatFileReader 30 | * @author Wojciech Gradkowski (wgradkowski@gmail.com) 31 | */ 32 | public class MatFileFilter { 33 | private Set filter; 34 | 35 | /** 36 | * Creates empty filter intance. 37 | * 38 | * Note: empty filter acceps all results. 39 | */ 40 | public MatFileFilter() { 41 | filter = new HashSet(); 42 | } 43 | 44 | /** 45 | * Create filter intance and add array names. 46 | * 47 | * @param names - array of names (needles) 48 | */ 49 | public MatFileFilter(String[] names) { 50 | this(); 51 | 52 | for (String name : names) { 53 | addArrayName(name); 54 | } 55 | } 56 | 57 | /** 58 | * Add array name to the filter. This array will be processed 59 | * while crawling thourg the MAT-file 60 | * 61 | * @param name - array name (needle) 62 | */ 63 | public void addArrayName(String name) { 64 | filter.add(name); 65 | } 66 | 67 | /** 68 | * Test if given name matches the filter. 69 | * 70 | * @param name - array name to be tested 71 | * @return - true if array (matrix) of this name should be processed 72 | */ 73 | public boolean matches(String name) { 74 | if (filter.size() == 0) { 75 | return true; 76 | } 77 | return filter.contains(name); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/MatFileHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io; 7 | 8 | import java.nio.ByteOrder; 9 | import java.util.Arrays; 10 | import java.util.Date; 11 | 12 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 13 | 14 | /** 15 | * MAT-file header 16 | * 17 | * Level 5 MAT-files begin with a 128-byte header made up of a 124 byte text field 18 | * and two, 16-bit flag fields 19 | * 20 | * @author Wojciech Gradkowski (wgradkowski@gmail.com) 21 | */ 22 | @SuppressFBWarnings(value = {"EI_EXPOSE_REP", "EI_EXPOSE_REP2"}, justification = "This code is unlikely to be used in a security-sensitive environment.") 23 | public class MatFileHeader { 24 | private static String DEFAULT_DESCRIPTIVE_TEXT = "MATLAB 5.0 MAT-file, Platform: " 25 | + System.getProperty("os.name") 26 | + ", CREATED on: "; 27 | public static final int DEFAULT_VERSION = 0x0100; 28 | public static final ByteOrder DEFAULT_ENDIAN = ByteOrder.BIG_ENDIAN; 29 | 30 | private static final byte[] ENDIAN_INDICATOR_BIG = new byte[]{(byte) 'M', (byte) 'I'}; 31 | private static final byte[] ENDIAN_INDICATOR_LITTLE = new byte[]{(byte) 'I', (byte) 'M'}; 32 | 33 | private int version; 34 | private String description; 35 | private final ByteOrder byteOrder; 36 | 37 | /** 38 | * Parses a MatFileHeader from its desciption and the raw bytes of the version and endian indicator. 39 | * 40 | * @param description - descriptive test 41 | * @param bversion - 2-byte array containing the version (raw from a MAT-File) 42 | * @param endianIndicator - 2-byte array containing the endian indicator (raw from a MAT-File( 43 | * @return 44 | */ 45 | public static MatFileHeader parseFrom(String description, byte[] bversion, byte[] endianIndicator) { 46 | int version; 47 | ByteOrder byteOrder = parseByteOrder(endianIndicator); 48 | if (byteOrder == ByteOrder.BIG_ENDIAN) { 49 | version = bversion[0] & 0xff | bversion[1] << 8; 50 | } else if (byteOrder == ByteOrder.LITTLE_ENDIAN) { 51 | version = bversion[1] & 0xff | bversion[0] << 8; 52 | } else { 53 | throw new IllegalArgumentException("Unknown byteOrder " + byteOrder); 54 | } 55 | return new MatFileHeader(description, version, byteOrder); 56 | } 57 | 58 | /** 59 | * Parses out the byte order based on a byte array containing 60 | * either 'MI' (big-endian) or 'IM' (little-endian). 61 | * 62 | * @param endianIndicator 2-byte long array holding the endian indicator 63 | */ 64 | public static ByteOrder parseByteOrder(byte[] endianIndicator) { 65 | if (Arrays.equals(ENDIAN_INDICATOR_BIG, endianIndicator)) { 66 | return ByteOrder.BIG_ENDIAN; 67 | } else if (Arrays.equals(ENDIAN_INDICATOR_LITTLE, endianIndicator)) { 68 | return ByteOrder.LITTLE_ENDIAN; 69 | } else { 70 | StringBuilder arrayBuilder = new StringBuilder(); 71 | for (int i = 0; i < endianIndicator.length; ++i) { 72 | arrayBuilder.append(endianIndicator[i]); 73 | } 74 | throw new IllegalArgumentException("Unknown endian indicator " + arrayBuilder.toString()); 75 | } 76 | } 77 | 78 | /** 79 | * New MAT-file header 80 | * 81 | * @param description - descriptive text (no longer than 116 characters) 82 | * @param version - by default is set to 0x0100 83 | * @param endianIndicator - byte array size of 2 indicating byte-swapping requirement 84 | */ 85 | public MatFileHeader(String description, int version, ByteOrder byteOrder) { 86 | this.description = description; 87 | this.version = version; 88 | this.byteOrder = byteOrder; 89 | } 90 | 91 | /** 92 | * Gets descriptive text 93 | * 94 | * @return 95 | */ 96 | public String getDescription() { 97 | return description; 98 | } 99 | 100 | /** 101 | * Gets endian indicator. Bytes written as "MI" suggest that byte-swapping operation is required 102 | * in order to interpret data correctly. If value is set to "IM" byte-swapping is not needed. 103 | * 104 | * @return - a byte array size of 2 105 | */ 106 | public byte[] getEndianIndicator() { 107 | if (byteOrder == ByteOrder.BIG_ENDIAN) { 108 | return Arrays.copyOf(ENDIAN_INDICATOR_BIG, 2); 109 | } else if (byteOrder == ByteOrder.LITTLE_ENDIAN) { 110 | return Arrays.copyOf(ENDIAN_INDICATOR_LITTLE, 2); 111 | } else { 112 | throw new IllegalArgumentException("Unknown byteOrder '" + byteOrder + "'"); 113 | } 114 | } 115 | 116 | /** 117 | * When creating a MAT-file, set version to 0x0100 118 | * 119 | * @return 120 | */ 121 | public int getVersion() { 122 | return version; 123 | } 124 | 125 | //@facotry 126 | /** 127 | * A factory. Creates new MatFileHeader instance with default header values: 128 | *
    129 | *
  • MAT-file is 5.0 version
  • 130 | *
  • version is set to 0x0100
  • 131 | *
  • no byte-swapping ("IM")
  • 132 | *
133 | * 134 | * @return - new MatFileHeader instance 135 | */ 136 | public static MatFileHeader createHeader() { 137 | return new MatFileHeader(DEFAULT_DESCRIPTIVE_TEXT + (new Date()).toString(), 138 | DEFAULT_VERSION, 139 | DEFAULT_ENDIAN); 140 | } 141 | 142 | /* (non-Javadoc) 143 | * @see java.lang.Object#toString() 144 | */ 145 | public String toString() { 146 | StringBuffer sb = new StringBuffer(); 147 | sb.append("["); 148 | sb.append("desriptive text: " + description); 149 | sb.append(", version: " + version); 150 | sb.append(", byteOrder: " + byteOrder); 151 | sb.append("]"); 152 | return sb.toString(); 153 | } 154 | 155 | public ByteOrder getByteOrder() { 156 | return byteOrder; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/MatFileType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io; 7 | 8 | /** Describes the type of Mat file. 9 | * @author Matthew Dawson 10 | */ 11 | public enum MatFileType { 12 | Regular, ReducedHeader 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/MatMCOSObjectInformation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | import com.jmatio.types.MLArray; 12 | 13 | /** 14 | * 15 | * @author Matthew Dawson 16 | */ 17 | class MatMCOSObjectInformation { 18 | MatMCOSObjectInformation(String className, int classId, int objectId, int segment2PropertiesIndex, int segment4PropertiesIndex) { 19 | this.className = className; 20 | 21 | this.objectId = objectId; 22 | this.classId = classId; 23 | 24 | this.segment2PropertiesIndex = segment2PropertiesIndex; 25 | this.segment4PropertiesIndex = segment4PropertiesIndex; 26 | } 27 | 28 | final String className; 29 | final int objectId; 30 | final int classId; 31 | final int segment2PropertiesIndex; 32 | final int segment4PropertiesIndex; 33 | final Map structure = new HashMap(); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/MatTag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io; 7 | 8 | import com.jmatio.common.MatDataTypes; 9 | 10 | /** 11 | * 12 | * @author Wojciech Gradkowski (wgradkowski@gmail.com) 13 | */ 14 | class MatTag { 15 | protected int type; 16 | protected int size; 17 | 18 | /** 19 | * @param type 20 | * @param size 21 | * @param compressed 22 | */ 23 | public MatTag(int type, int size) { 24 | this.type = type; 25 | this.size = size; 26 | } 27 | 28 | /** 29 | * Calculate padding 30 | */ 31 | protected int getPadding(int size, boolean compressed) { 32 | int padding; 33 | //data not packed in the tag 34 | if (!compressed) { 35 | int b; 36 | padding = (b = (((size / sizeOf()) % (8 / sizeOf())) * sizeOf())) != 0 ? 8 - b : 0; 37 | } else //data _packed_ in the tag (compressed) 38 | { 39 | int b; 40 | padding = (b = (((size / sizeOf()) % (4 / sizeOf())) * sizeOf())) != 0 ? 4 - b : 0; 41 | } 42 | return padding; 43 | } 44 | 45 | /* (non-Javadoc) 46 | * @see java.lang.Object#toString() 47 | */ 48 | public String toString() { 49 | String s; 50 | 51 | s = "[tag: " + MatDataTypes.typeToString(type) + " size: " + size + "]"; 52 | 53 | return s; 54 | } 55 | 56 | /** 57 | * Get size of single data in this tag. 58 | * 59 | * @return - number of bytes for single data 60 | */ 61 | public int sizeOf() { 62 | return MatDataTypes.sizeOf(type); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/MatlabIOException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io; 7 | 8 | import java.io.IOException; 9 | 10 | /** 11 | * MAT-file reader/writer exception 12 | * 13 | * @author Wojciech Gradkowski (wgradkowski@gmail.com) 14 | */ 15 | @SuppressWarnings("serial") 16 | public class MatlabIOException extends IOException { 17 | public MatlabIOException(String s) { 18 | super(s); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/OSArrayTag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io; 7 | 8 | import java.io.DataOutputStream; 9 | import java.io.IOException; 10 | import java.nio.ByteBuffer; 11 | 12 | /** 13 | * Tiny class that represents MAT-file TAG 14 | * It simplifies writing data. Automates writing padding for instance. 15 | */ 16 | class OSArrayTag extends MatTag { 17 | private ByteBuffer data; 18 | 19 | /** 20 | * Creates TAG and stets its size as size of byte array 21 | * 22 | * @param type 23 | * @param data 24 | */ 25 | public OSArrayTag(int type, byte[] data) { 26 | this(type, ByteBuffer.wrap(data)); 27 | } 28 | 29 | /** 30 | * Creates TAG and stets its size as size of byte array 31 | * 32 | * @param type 33 | * @param data 34 | */ 35 | public OSArrayTag(int type, ByteBuffer data) { 36 | super(type, data.limit()); 37 | this.data = data; 38 | data.rewind(); 39 | } 40 | 41 | /** 42 | * Writes tag and data to DataOutputStream. Wites padding if neccesary. 43 | * 44 | * @param os 45 | * @throws IOException 46 | */ 47 | public void writeTo(DataOutputStream os) throws IOException { 48 | 49 | int padding; 50 | if (size <= 4 && size > 0) { 51 | // Use small data element format (Page 1-10 in "MATLAB 7 MAT-File Format", September 2010 revision) 52 | os.writeShort(size); 53 | os.writeShort(type); 54 | padding = getPadding(data.limit(), true); 55 | } else { 56 | os.writeInt(type); 57 | os.writeInt(size); 58 | padding = getPadding(data.limit(), false); 59 | } 60 | 61 | int maxBuffSize = 1024; 62 | int writeBuffSize = data.remaining() < maxBuffSize ? data.remaining() : maxBuffSize; 63 | byte[] tmp = new byte[writeBuffSize]; 64 | while (data.remaining() > 0) { 65 | int length = data.remaining() > tmp.length ? tmp.length : data.remaining(); 66 | data.get(tmp, 0, length); 67 | os.write(tmp, 0, length); 68 | } 69 | 70 | if (padding > 0) { 71 | os.write(new byte[padding]); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/SimulinkDecoder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io; 7 | 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.io.UnsupportedEncodingException; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | import com.jmatio.common.MatDataTypes; 15 | 16 | /** This class decodes the Simulink base64 representation of a MAT file. 17 | * 18 | * @author Matthew Dawson 19 | */ 20 | public class SimulinkDecoder extends InputStream { 21 | public SimulinkDecoder(String input) { 22 | try { 23 | this.input = input.getBytes(MatDataTypes.CHARSET); 24 | for (byte i = 0; i < 64; ++i) { 25 | decoderRing.put((byte) (i + ' '), i); 26 | } 27 | } catch (UnsupportedEncodingException e) { 28 | throw new RuntimeException(e); 29 | } 30 | } 31 | 32 | @Override 33 | public int read() throws IOException { 34 | try { 35 | int ret; 36 | switch (pos % 4) { 37 | case 0: { 38 | byte first = decoderRing.get(input[pos++]); 39 | byte second = decoderRing.get(input[pos++]); 40 | 41 | ret = (first << 2) | (second >> 4); 42 | leftover = (byte) (second & 0x0f); 43 | break; 44 | } 45 | case 2: { 46 | byte next = decoderRing.get(input[pos++]); 47 | 48 | ret = (leftover << 4) | (next >> 2); 49 | leftover = (byte) (next & 0x03); 50 | break; 51 | } 52 | case 3: { 53 | byte next = decoderRing.get(input[pos++]); 54 | ret = (leftover << 6) | next; 55 | break; 56 | } 57 | case -1: { // We need to explicitly deal with the -1 case, as -1 % 4 in Java is -1. 58 | return -1; 59 | } 60 | default: 61 | throw new RuntimeException("Case " + (pos % 4)); 62 | } 63 | 64 | return ret; 65 | } catch (ArrayIndexOutOfBoundsException ex) { 66 | pos = -1; // Ensure that the exception will be re-thrown, avoiding a buffer overflow. 67 | return -1; 68 | } 69 | } 70 | 71 | private final byte[] input; 72 | private int pos; 73 | private byte leftover; 74 | final private Map decoderRing = new HashMap(); 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/Unsafe9R.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io; 7 | 8 | import java.lang.reflect.Field; 9 | import java.lang.reflect.Method; 10 | import java.nio.ByteBuffer; 11 | import java.security.AccessController; 12 | import java.security.PrivilegedExceptionAction; 13 | 14 | import sun.misc.Unsafe; 15 | 16 | /** 17 | * Provides reflective access to new methods that were added to sun.misc.Unsafe 18 | * in Java 9. Earlier platforms will fall back to a a behavior-equivalent 19 | * implementation that uses available operations. 20 | *

21 | * ========== JDK Warning: sun.misc.Unsafe ========== 22 | *

23 | * A collection of methods for performing low-level, unsafe operations. 24 | * Although the class and all methods are public, use of this class is 25 | * limited because only trusted code can obtain instances of it. 26 | * 27 | * Note: It is the resposibility of the caller to make sure 28 | * arguments are checked before methods of this class are 29 | * called. While some rudimentary checks are performed on the input, 30 | * the checks are best effort and when performance is an overriding 31 | * priority, as when methods of this class are optimized by the 32 | * runtime compiler, some or all checks (if any) may be elided. Hence, 33 | * the caller must not rely on the checks and corresponding 34 | * exceptions! 35 | * 36 | * @author Florian Enner 37 | */ 38 | class Unsafe9R { 39 | 40 | /** 41 | * Invokes the given direct byte buffer's cleaner, if any. 42 | * 43 | * @param directBuffer a direct byte buffer 44 | * @throws NullPointerException if {@code directBuffer} is null 45 | * @throws IllegalArgumentException if {@code directBuffer} is non-direct 46 | * @throws IllegalArgumentException if {@code directBuffer} is slice or duplicate (Java 9+ only) 47 | */ 48 | public static void invokeCleaner(ByteBuffer directBuffer) { 49 | if (!directBuffer.isDirect()) 50 | throw new IllegalArgumentException("buffer is non-direct"); 51 | if (useJava9) 52 | Java9.invokeCleaner(directBuffer); 53 | else { 54 | Java6.invokeCleaner(directBuffer); 55 | } 56 | } 57 | 58 | static { 59 | 60 | // Get Java version 61 | String version = System.getProperty("java.specification.version", "6"); 62 | String majorVersion = version.startsWith("1.") ? version.substring(2) : version; 63 | useJava9 = Integer.parseInt(majorVersion) >= 9; 64 | 65 | } 66 | 67 | private static final boolean useJava9; 68 | 69 | private static class Java9 { 70 | 71 | static void invokeCleaner(ByteBuffer buffer) { 72 | try { 73 | INVOKE_CLEANER.invoke(UNSAFE, buffer); 74 | } catch (Exception e) { 75 | throw new IllegalStateException("Java 9 Cleaner failed to free DirectBuffer", e); 76 | } 77 | } 78 | 79 | static final Unsafe UNSAFE; 80 | static final Method INVOKE_CLEANER; 81 | 82 | static { 83 | try { 84 | final PrivilegedExceptionAction action = new PrivilegedExceptionAction() { 85 | @Override 86 | public Unsafe run() throws Exception { 87 | final Field f = Unsafe.class.getDeclaredField("theUnsafe"); 88 | f.setAccessible(true); 89 | return (Unsafe) f.get(null); 90 | } 91 | }; 92 | UNSAFE = AccessController.doPrivileged(action); 93 | INVOKE_CLEANER = UNSAFE.getClass().getMethod("invokeCleaner", ByteBuffer.class); 94 | 95 | } catch (final Exception ex) { 96 | throw new IllegalStateException("Java 9 Cleaner not available", ex); 97 | } 98 | 99 | } 100 | 101 | } 102 | 103 | private static class Java6 { 104 | 105 | static void invokeCleaner(ByteBuffer buffer) { 106 | try { 107 | Object cleaner = GET_CLEANER.invoke(buffer); 108 | if (cleaner != null) 109 | INVOKE_CLEANER.invoke(cleaner); 110 | } catch (Exception e) { 111 | throw new IllegalStateException("Java 6 Cleaner failed to free DirectBuffer", e); 112 | } 113 | } 114 | 115 | static { 116 | try { 117 | GET_CLEANER = Class.forName("sun.nio.ch.DirectBuffer").getMethod("cleaner"); 118 | INVOKE_CLEANER = Class.forName("sun.misc.Cleaner").getMethod("clean"); 119 | } catch (Exception e) { 120 | throw new IllegalStateException("Java 6 Cleaner not available", e); 121 | } 122 | } 123 | 124 | static final Method GET_CLEANER; 125 | static final Method INVOKE_CLEANER; 126 | 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/stream/BufferedOutputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io.stream; 7 | 8 | import java.io.IOException; 9 | import java.io.OutputStream; 10 | import java.nio.ByteBuffer; 11 | 12 | public abstract class BufferedOutputStream extends OutputStream { 13 | /** 14 | * Returns the backing {@link ByteBuffer} 15 | * @return 16 | */ 17 | public abstract ByteBuffer buffer() throws IOException; 18 | 19 | public abstract long size() throws IOException; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/stream/ByteBufferInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io.stream; 7 | 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.nio.ByteBuffer; 11 | 12 | public class ByteBufferInputStream extends InputStream { 13 | private ByteBuffer buf; 14 | 15 | private int limit; 16 | 17 | public ByteBufferInputStream(final ByteBuffer buf, final int limit) { 18 | this.buf = buf; 19 | this.limit = limit; 20 | } 21 | 22 | @Override 23 | public synchronized int read() throws IOException { 24 | if (!(limit > 0)) { 25 | return -1; 26 | } 27 | limit--; 28 | return buf.get() & 0xFF; 29 | } 30 | 31 | @Override 32 | public synchronized int read(byte[] bytes, int off, int len) 33 | throws IOException { 34 | if (!(limit > 0)) { 35 | return -1; 36 | } 37 | len = Math.min(len, limit); 38 | // Read only what's left 39 | buf.get(bytes, off, len); 40 | limit -= len; 41 | return len; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/stream/DataOutputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io.stream; 7 | 8 | import java.io.IOException; 9 | import java.nio.ByteBuffer; 10 | 11 | interface DataOutputStream { 12 | /** 13 | * Returns the current size of this stream. 14 | * 15 | * @return the current size of this stream. 16 | * @throws IOException 17 | */ 18 | public abstract int size() throws IOException; 19 | 20 | /** 21 | * Returns the current {@link ByteBuffer} mapped on the target file. 22 | *

23 | * Note: the {@link ByteBuffer} has READ ONLY access. 24 | * 25 | * @return the {@link ByteBuffer} 26 | * @throws IOException 27 | */ 28 | public abstract ByteBuffer getByteBuffer() throws IOException; 29 | 30 | /** 31 | * Writes a sequence of bytes to this stream from the given buffer. 32 | * 33 | * @param byteBuffer 34 | * the source {@link ByteBuffer} 35 | * @throws IOException 36 | */ 37 | public abstract void write(ByteBuffer byteBuffer) throws IOException; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/stream/HeapBufferDataOutputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io.stream; 7 | 8 | import java.io.ByteArrayOutputStream; 9 | import java.io.IOException; 10 | import java.nio.ByteBuffer; 11 | 12 | public class HeapBufferDataOutputStream extends ByteArrayOutputStream implements DataOutputStream { 13 | private static final int BUFFER_SIZE = 1024; 14 | 15 | public ByteBuffer getByteBuffer() throws IOException { 16 | return ByteBuffer.wrap(super.buf); 17 | } 18 | 19 | public void write(ByteBuffer byteBuffer) throws IOException { 20 | 21 | byte[] tmp = new byte[BUFFER_SIZE]; 22 | 23 | while (byteBuffer.hasRemaining()) { 24 | int length = Math.min(byteBuffer.remaining(), tmp.length); 25 | byteBuffer.get(tmp, 0, length); 26 | write(tmp, 0, length); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/io/stream/MatFileInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io.stream; 7 | 8 | import java.io.IOException; 9 | import java.nio.ByteBuffer; 10 | 11 | import com.jmatio.common.MatDataTypes; 12 | import com.jmatio.types.ByteStorageSupport; 13 | 14 | /** 15 | * MAT-file input stream class. 16 | * 17 | * @author Wojciech Gradkowski 18 | */ 19 | public class MatFileInputStream { 20 | private final int type; 21 | private final ByteBuffer buf; 22 | 23 | /** 24 | * Attach MAT-file input stream to InputStream 25 | * 26 | * @param is - input stream 27 | * @param type - type of data in the stream 28 | * @see com.jmatio.common.MatDataTypes 29 | */ 30 | public MatFileInputStream(ByteBuffer buf, int type) { 31 | this.type = type; 32 | this.buf = buf; 33 | } 34 | 35 | /** 36 | * Reads data (number of bytes red is determined by data type) 37 | * from the stream to int. 38 | * 39 | * @return 40 | * @throws IOException 41 | */ 42 | public int readInt() throws IOException { 43 | switch (type) { 44 | case MatDataTypes.miUINT8: 45 | return (int) (buf.get() & 0xFF); 46 | case MatDataTypes.miINT8: 47 | return (int) buf.get(); 48 | case MatDataTypes.miUINT16: 49 | return (int) (buf.getShort() & 0xFFFF); 50 | case MatDataTypes.miINT16: 51 | return (int) buf.getShort(); 52 | case MatDataTypes.miUINT32: 53 | return (int) buf.getInt(); 54 | case MatDataTypes.miINT32: 55 | return (int) buf.getInt(); 56 | case MatDataTypes.miUINT64: 57 | return (int) buf.getLong(); 58 | case MatDataTypes.miINT64: 59 | return (int) buf.getLong(); 60 | case MatDataTypes.miDOUBLE: 61 | return (int) buf.getDouble(); 62 | default: 63 | throw new IllegalArgumentException("Unknown data type: " + type); 64 | } 65 | } 66 | 67 | /** 68 | * Reads data (number of bytes red is determined by data type) 69 | * from the stream to char. 70 | * 71 | * @return - char 72 | * @throws IOException 73 | */ 74 | public char readChar() throws IOException { 75 | switch (type) { 76 | case MatDataTypes.miUINT8: 77 | return (char) (buf.get() & 0xFF); 78 | case MatDataTypes.miINT8: 79 | return (char) buf.get(); 80 | case MatDataTypes.miUINT16: 81 | return (char) (buf.getShort() & 0xFFFF); 82 | case MatDataTypes.miINT16: 83 | return (char) buf.getShort(); 84 | case MatDataTypes.miUINT32: 85 | return (char) buf.getInt(); 86 | case MatDataTypes.miINT32: 87 | return (char) buf.getInt(); 88 | case MatDataTypes.miDOUBLE: 89 | return (char) buf.getDouble(); 90 | case MatDataTypes.miUTF8: 91 | return (char) buf.get(); 92 | default: 93 | throw new IllegalArgumentException("Unknown data type: " + type); 94 | } 95 | } 96 | 97 | /** 98 | * Reads data (number of bytes red is determined by data type) 99 | * from the stream to double. 100 | * 101 | * @return - double 102 | * @throws IOException 103 | */ 104 | public double readDouble() throws IOException { 105 | switch (type) { 106 | case MatDataTypes.miUINT8: 107 | return (double) (buf.get() & 0xFF); 108 | case MatDataTypes.miINT8: 109 | return (double) buf.get(); 110 | case MatDataTypes.miUINT16: 111 | return (double) (buf.getShort() & 0xFFFF); 112 | case MatDataTypes.miINT16: 113 | return (double) buf.getShort(); 114 | case MatDataTypes.miUINT32: 115 | return (double) buf.getInt(); 116 | case MatDataTypes.miINT32: 117 | return (double) buf.getInt(); 118 | case MatDataTypes.miDOUBLE: 119 | return (double) buf.getDouble(); 120 | default: 121 | throw new IllegalArgumentException("Unknown data type: " + type); 122 | } 123 | } 124 | 125 | public byte readByte() { 126 | switch (type) { 127 | case MatDataTypes.miUINT8: 128 | return (byte) (buf.get() & 0xFF); 129 | case MatDataTypes.miINT8: 130 | return (byte) buf.get(); 131 | case MatDataTypes.miUINT16: 132 | return (byte) (buf.getShort() & 0xFFFF); 133 | case MatDataTypes.miINT16: 134 | return (byte) buf.getShort(); 135 | case MatDataTypes.miUINT32: 136 | return (byte) buf.getInt(); 137 | case MatDataTypes.miINT32: 138 | return (byte) buf.getInt(); 139 | case MatDataTypes.miDOUBLE: 140 | return (byte) buf.getDouble(); 141 | case MatDataTypes.miUTF8: 142 | case MatDataTypes.miUTF16: 143 | case MatDataTypes.miUTF32: 144 | return (byte) buf.get(); 145 | default: 146 | throw new IllegalArgumentException("Unknown data type: " + type); 147 | } 148 | } 149 | 150 | /** 151 | * Reads the data into a {@link ByteBuffer}. This method is 152 | * only supported for arrays with backing ByteBuffer ({@link ByteStorageSupport}). 153 | * 154 | * @param dest 155 | * the destination {@link ByteBuffer} 156 | * @param elements 157 | * the number of elements to read into a buffer 158 | * @param storage 159 | * the backing {@link ByteStorageSupport} that 160 | * gives information how data should be interpreted 161 | * @return reference to the destination {@link ByteBuffer} 162 | * @throws IOException 163 | * if buffer is under-fed, or another IO problem occurs 164 | */ 165 | public ByteBuffer readToByteBuffer(ByteBuffer dest, int elements, 166 | ByteStorageSupport storage) throws IOException { 167 | 168 | int bytesAllocated = storage.getBytesAllocated(); 169 | int size = elements * storage.getBytesAllocated(); 170 | 171 | //direct buffer copy 172 | if (MatDataTypes.sizeOf(type) == bytesAllocated && buf.order().equals(dest.order())) { 173 | int bufMaxSize = 1024; 174 | int bufSize = Math.min(buf.remaining(), bufMaxSize); 175 | int bufPos = buf.position(); 176 | 177 | byte[] tmp = new byte[bufSize]; 178 | 179 | while (dest.remaining() > 0) { 180 | int length = Math.min(dest.remaining(), tmp.length); 181 | buf.get(tmp, 0, length); 182 | dest.put(tmp, 0, length); 183 | } 184 | buf.position(bufPos + size); 185 | } else { 186 | //because Matlab writes data not respectively to the declared 187 | //matrix type, the reading is not straight forward (as above) 188 | Class clazz = storage.getStorageClazz(); 189 | while (dest.remaining() > 0) { 190 | if (clazz.equals(Double.class)) { 191 | dest.putDouble(readDouble()); 192 | } else if (clazz.equals(Byte.class)) { 193 | dest.put(readByte()); 194 | } else if (clazz.equals(Integer.class)) { 195 | dest.putInt(readInt()); 196 | } else if (clazz.equals(Long.class)) { 197 | dest.putLong(readLong()); 198 | } else if (clazz.equals(Float.class)) { 199 | dest.putFloat(readFloat()); 200 | } else if (clazz.equals(Short.class)) { 201 | dest.putShort(readShort()); 202 | } else { 203 | throw new RuntimeException("Not supported buffer reader for " + clazz); 204 | } 205 | } 206 | } 207 | dest.rewind(); 208 | return dest; 209 | } 210 | 211 | private float readFloat() { 212 | switch (type) { 213 | case MatDataTypes.miUINT8: 214 | return (float) (buf.get() & 0xFF); 215 | case MatDataTypes.miINT8: 216 | return (float) buf.get(); 217 | case MatDataTypes.miUINT16: 218 | return (float) (buf.getShort() & 0xFFFF); 219 | case MatDataTypes.miINT16: 220 | return (float) buf.getShort(); 221 | case MatDataTypes.miUINT32: 222 | return (float) buf.getInt(); 223 | case MatDataTypes.miINT32: 224 | return (float) buf.getInt(); 225 | case MatDataTypes.miSINGLE: 226 | return (float) buf.getFloat(); 227 | case MatDataTypes.miDOUBLE: 228 | return (float) buf.getDouble(); 229 | default: 230 | throw new IllegalArgumentException("Unknown data type: " + type); 231 | } 232 | } 233 | 234 | private short readShort() { 235 | switch (type) { 236 | case MatDataTypes.miUINT8: 237 | return (short) (buf.get() & 0xFF); 238 | case MatDataTypes.miINT8: 239 | return (short) buf.get(); 240 | case MatDataTypes.miUINT16: 241 | return (short) (buf.getShort() & 0xFFFF); 242 | case MatDataTypes.miINT16: 243 | return (short) buf.getShort(); 244 | case MatDataTypes.miUINT32: 245 | return (short) buf.getInt(); 246 | case MatDataTypes.miINT32: 247 | return (short) buf.getInt(); 248 | case MatDataTypes.miUINT64: 249 | return (short) buf.getLong(); 250 | case MatDataTypes.miINT64: 251 | return (short) buf.getLong(); 252 | case MatDataTypes.miDOUBLE: 253 | return (short) buf.getDouble(); 254 | default: 255 | throw new IllegalArgumentException("Unknown data type: " + type); 256 | } 257 | } 258 | 259 | private long readLong() { 260 | switch (type) { 261 | case MatDataTypes.miUINT8: 262 | return (long) (buf.get() & 0xFF); 263 | case MatDataTypes.miINT8: 264 | return (long) buf.get(); 265 | case MatDataTypes.miUINT16: 266 | return (long) (buf.getShort() & 0xFFFF); 267 | case MatDataTypes.miINT16: 268 | return (long) buf.getShort(); 269 | case MatDataTypes.miUINT32: 270 | return (long) buf.getInt(); 271 | case MatDataTypes.miINT32: 272 | return (long) buf.getInt(); 273 | case MatDataTypes.miUINT64: 274 | return (long) buf.getLong(); 275 | case MatDataTypes.miINT64: 276 | return (long) buf.getLong(); 277 | case MatDataTypes.miDOUBLE: 278 | return (long) buf.getDouble(); 279 | default: 280 | throw new IllegalArgumentException("Unknown data type: " + type); 281 | } 282 | } 283 | 284 | public void skip(int padding) { 285 | buf.position(buf.position() + padding); 286 | } 287 | 288 | } 289 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/ByteStorageSupport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | public interface ByteStorageSupport { 9 | int getBytesAllocated(); 10 | 11 | T buldFromBytes(byte[] bytes); 12 | 13 | byte[] getByteArray(T value); 14 | 15 | Class getStorageClazz(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.io.UnsupportedEncodingException; 9 | import java.util.Arrays; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | import com.jmatio.common.MatDataTypes; 14 | 15 | public class MLArray { 16 | 17 | /* Matlab Array Types (Classes) */ 18 | public static final int mxUNKNOWN_CLASS = 0; 19 | public static final int mxCELL_CLASS = 1; 20 | public static final int mxSTRUCT_CLASS = 2; 21 | public static final int mxOBJECT_CLASS = 3; 22 | public static final int mxCHAR_CLASS = 4; 23 | public static final int mxSPARSE_CLASS = 5; 24 | public static final int mxDOUBLE_CLASS = 6; 25 | public static final int mxSINGLE_CLASS = 7; 26 | public static final int mxINT8_CLASS = 8; 27 | public static final int mxUINT8_CLASS = 9; 28 | public static final int mxINT16_CLASS = 10; 29 | public static final int mxUINT16_CLASS = 11; 30 | public static final int mxINT32_CLASS = 12; 31 | public static final int mxUINT32_CLASS = 13; 32 | public static final int mxINT64_CLASS = 14; 33 | public static final int mxUINT64_CLASS = 15; 34 | public static final int mxFUNCTION_CLASS = 16; 35 | public static final int mxOPAQUE_CLASS = 17; 36 | 37 | public static final int mtFLAG_COMPLEX = 0x0800; 38 | public static final int mtFLAG_GLOBAL = 0x0400; 39 | public static final int mtFLAG_LOGICAL = 0x0200; 40 | public static final int mtFLAG_TYPE = 0xff; 41 | 42 | @Nonnull 43 | protected final int dims[]; 44 | @Nonnull 45 | public String name; 46 | protected final int attributes; 47 | protected final int type; 48 | private final int dimStrides[]; // Used to convert multidimensional index to linear index 49 | 50 | public static final String DEFAULT_NAME = "@"; 51 | 52 | public MLArray(String name, int[] dims, int type, int attributes) { 53 | this.dims = Arrays.copyOf(dims, dims.length); 54 | 55 | if (name != null && !name.equals("")) { 56 | this.name = name; 57 | } else { 58 | this.name = DEFAULT_NAME; //default name 59 | } 60 | 61 | this.type = type; 62 | this.attributes = attributes; 63 | 64 | // the indices are processed in order from 0 to max in order to match Matlab's 65 | // column major ordering of storage in the .mat file 66 | dimStrides = new int[dims.length]; 67 | for (int dimIx = 0, f = 1; dimIx < dims.length; dimIx++) { 68 | dimStrides[dimIx] = f; 69 | f *= dims[dimIx]; 70 | } 71 | } 72 | 73 | /** 74 | * Returns the one-dim index for the multi-dimensional indexes. Compatible with matlab multi-dimensional indexing. 75 | * 76 | * Note: this performs the same logical function as getIndex, but the indices are computed in column major order 77 | * for compatibility with .mat files generated by Matlab. 78 | * 79 | * @param indexes Length must be same as number of dimensions. Element value must be >= 0 and < dimension size for the corresponding dimension. 80 | * @return The linear index 81 | */ 82 | public int getIndex(int... indexes) { 83 | if (indexes.length != dims.length) { 84 | throw new IllegalArgumentException("Cannot use " + indexes.length + " indexes for " + dims.length + " dimensions."); 85 | } 86 | int ix = 0; 87 | for (int dimIx = 0; dimIx < indexes.length; dimIx++) { 88 | ix += dimStrides[dimIx] * validateDimSize(dimIx, indexes[dimIx]); 89 | } 90 | return ix; 91 | } 92 | 93 | private int validateDimSize(int dimIx, int ixInDim) { 94 | if (dims[dimIx] > ixInDim) { 95 | return ixInDim; 96 | } 97 | throw new IllegalArgumentException("Index " + ixInDim + " does not exist for dimension " + dimIx); 98 | } 99 | 100 | /** 101 | * Gets array name 102 | * 103 | * @return - array name 104 | */ 105 | public String getName() { 106 | return name; 107 | } 108 | 109 | public int getFlags() { 110 | return type & mtFLAG_TYPE | attributes & 0xffffff00; 111 | } 112 | 113 | public byte[] getNameToByteArray() { 114 | try { 115 | return name.getBytes(MatDataTypes.CHARSET); 116 | } catch (UnsupportedEncodingException e) { 117 | throw new RuntimeException(e); 118 | } 119 | } 120 | 121 | public int[] getDimensions() { 122 | return Arrays.copyOf(dims, dims.length); 123 | } 124 | 125 | public int getM() { 126 | return dims[0]; 127 | } 128 | 129 | public int getN() { 130 | int i = dims[1]; 131 | for (int j = 2; j < dims.length; j++) { 132 | i *= dims[j]; 133 | } 134 | return i; 135 | } 136 | 137 | public int getNDimensions() { 138 | return dims.length; 139 | } 140 | 141 | public int getSize() { 142 | return getM() * getN(); 143 | } 144 | 145 | public int getType() { 146 | return type; 147 | } 148 | 149 | public boolean isEmpty() { 150 | return getN() == 0; 151 | } 152 | 153 | public static final String typeToString(int type) { 154 | String s; 155 | // @formatter:off 156 | switch (type) { 157 | case mxUNKNOWN_CLASS: s = "unknown"; break; 158 | case mxCELL_CLASS: s = "cell"; break; 159 | case mxSTRUCT_CLASS: s = "struct"; break; 160 | case mxCHAR_CLASS: s = "char"; break; 161 | case mxSPARSE_CLASS: s = "sparse"; break; 162 | case mxDOUBLE_CLASS: s = "double"; break; 163 | case mxSINGLE_CLASS: s = "single"; break; 164 | case mxINT8_CLASS: s = "int8"; break; 165 | case mxUINT8_CLASS: s = "uint8"; break; 166 | case mxINT16_CLASS: s = "int16"; break; 167 | case mxUINT16_CLASS: s = "uint16"; break; 168 | case mxINT32_CLASS: s = "int32"; break; 169 | case mxUINT32_CLASS: s = "uint32"; break; 170 | case mxINT64_CLASS: s = "int64"; break; 171 | case mxUINT64_CLASS: s = "uint64"; break; 172 | case mxFUNCTION_CLASS: s = "function_handle"; break; 173 | case mxOPAQUE_CLASS: s = "opaque"; break; 174 | case mxOBJECT_CLASS: s = "object"; break; 175 | default: s = "unknown"; break; 176 | } 177 | // @formatter:on 178 | return s; 179 | } 180 | 181 | public boolean isCell() { 182 | return type == mxCELL_CLASS; 183 | } 184 | 185 | public boolean isChar() { 186 | return type == mxCHAR_CLASS; 187 | } 188 | 189 | public boolean isComplex() { 190 | return (attributes & mtFLAG_COMPLEX) == mtFLAG_COMPLEX; 191 | } 192 | 193 | public boolean isSparse() { 194 | return type == mxSPARSE_CLASS; 195 | } 196 | 197 | public boolean isStruct() { 198 | return type == mxSTRUCT_CLASS; 199 | } 200 | 201 | public boolean isDouble() { 202 | return type == mxDOUBLE_CLASS; 203 | } 204 | 205 | public boolean isSingle() { 206 | return type == mxSINGLE_CLASS; 207 | } 208 | 209 | public boolean isInt8() { 210 | return type == mxINT8_CLASS; 211 | } 212 | 213 | public boolean isUint8() { 214 | return type == mxUINT8_CLASS; 215 | } 216 | 217 | public boolean isInt16() { 218 | return type == mxINT16_CLASS; 219 | } 220 | 221 | public boolean isUint16() { 222 | return type == mxUINT16_CLASS; 223 | } 224 | 225 | public boolean isInt32() { 226 | return type == mxINT32_CLASS; 227 | } 228 | 229 | public boolean isUint32() { 230 | return type == mxUINT32_CLASS; 231 | } 232 | 233 | public boolean isInt64() { 234 | return type == mxINT64_CLASS; 235 | } 236 | 237 | public boolean isUint64() { 238 | return type == mxUINT64_CLASS; 239 | } 240 | 241 | public boolean isObject() { 242 | return type == mxOBJECT_CLASS; 243 | } 244 | 245 | public boolean isOpaque() { 246 | return type == mxOPAQUE_CLASS; 247 | } 248 | 249 | public boolean isLogical() { 250 | return (attributes & mtFLAG_LOGICAL) == mtFLAG_LOGICAL; 251 | } 252 | 253 | public boolean isFunctionObject() { 254 | return type == mxFUNCTION_CLASS; 255 | } 256 | 257 | public boolean isUnknown() { 258 | return type == mxUNKNOWN_CLASS; 259 | } 260 | 261 | protected int getIndex(int m, int n) { 262 | return m + n * getM(); 263 | } 264 | 265 | @Override 266 | public String toString() { 267 | StringBuilder sb = new StringBuilder(); 268 | sb.append('['); 269 | if (dims.length > 3) { 270 | sb.append(dims.length); 271 | sb.append('D'); 272 | } else { 273 | sb.append(dims[0]); 274 | sb.append('x'); 275 | sb.append(dims[1]); 276 | if (dims.length == 3) { 277 | sb.append('x'); 278 | sb.append(dims[2]); 279 | } 280 | } 281 | sb.append(" "); 282 | sb.append(typeToString(type)); 283 | if (isLogical()) { 284 | sb.append(" (logical)"); 285 | } 286 | sb.append(" array"); 287 | if (isSparse()) { 288 | sb.append(" (sparse"); 289 | if (isComplex()) { 290 | sb.append(" complex"); 291 | } 292 | sb.append(")"); 293 | } else if (isComplex()) { 294 | sb.append(" (complex)"); 295 | } 296 | sb.append(']'); 297 | return sb.toString(); 298 | } 299 | 300 | public String contentToString() { 301 | return "content cannot be displayed"; 302 | } 303 | 304 | /** Clears any memory used by this MLArray. The array cannot be used after this has been called. */ 305 | public void dispose() {} 306 | } 307 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLCell.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.util.ArrayList; 9 | 10 | public class MLCell extends MLArray { 11 | private ArrayList cells; 12 | 13 | public MLCell(String name, int[] dims) { 14 | this(name, dims, MLArray.mxCELL_CLASS, 0); 15 | } 16 | 17 | public MLCell(String name, int[] dims, int type, int attributes) { 18 | super(name, dims, type, attributes); 19 | 20 | cells = new ArrayList(getM() * getN()); 21 | 22 | for (int i = 0; i < getM() * getN(); i++) { 23 | cells.add(new MLEmptyArray()); 24 | } 25 | } 26 | 27 | public void set(MLArray value, int m, int n) { 28 | cells.set(getIndex(m, n), value); 29 | } 30 | 31 | public void set(MLArray value, int index) { 32 | cells.set(index, value); 33 | } 34 | 35 | public MLArray get(int m, int n) { 36 | return cells.get(getIndex(m, n)); 37 | } 38 | 39 | public MLArray get(int index) { 40 | return cells.get(index); 41 | } 42 | 43 | public int getIndex(int m, int n) { 44 | return m + n * getM(); 45 | } 46 | 47 | public ArrayList cells() { 48 | return cells; 49 | } 50 | 51 | public String contentToString() { 52 | StringBuffer sb = new StringBuffer(); 53 | sb.append(name + " = \n"); 54 | 55 | for (int m = 0; m < getM(); m++) { 56 | sb.append("\t"); 57 | for (int n = 0; n < getN(); n++) { 58 | sb.append(get(m, n)); 59 | sb.append("\t"); 60 | } 61 | sb.append("\n"); 62 | } 63 | return sb.toString(); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLChar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.util.Arrays; 9 | 10 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 11 | 12 | public class MLChar extends MLArray { 13 | Character[] chars; 14 | 15 | /** 16 | * Creates the 1 x {@link String#length()} {@link MLChar} from the given 17 | * String. 18 | * 19 | * @param name the {@link MLArray} name 20 | * @param value the String 21 | */ 22 | public MLChar(String name, String value) { 23 | this(name, new int[]{1, value.length()}, MLArray.mxCHAR_CLASS, 0); 24 | set(value); 25 | } 26 | 27 | /** 28 | * Create the {@link MLChar} from array of {@link String}s. 29 | * 30 | * @param name the {@link MLArray} name 31 | * @param values the array of {@link String}s 32 | */ 33 | public MLChar(String name, String[] values) { 34 | this(name, new int[]{values.length, values.length > 0 ? getMaxLength(values) : 0}, MLArray.mxCHAR_CLASS, 0); 35 | 36 | for (int i = 0; i < values.length; i++) { 37 | set(values[i], i); 38 | } 39 | } 40 | 41 | /** 42 | * Returns the maximum {@link String} length of array of {@link String}s. 43 | * @param values the array of {@link String}s 44 | * @return the maximum {@link String} length of array of {@link String}s 45 | */ 46 | private static int getMaxLength(String[] values) { 47 | int result = 0; 48 | 49 | for (int i = 0, curr = 0; i < values.length; i++) { 50 | if ((curr = values[i].length()) > result) { 51 | result = curr; 52 | } 53 | } 54 | return result; 55 | } 56 | 57 | /** 58 | * Added method to allow initialization of a char array representing 59 | * an array of strings. 60 | * 61 | * @param name 62 | * @param values 63 | * @param maxlen 64 | */ 65 | public MLChar(String name, String[] values, int maxlen) { 66 | this(name, new int[]{values.length, maxlen}, MLArray.mxCHAR_CLASS, 0); 67 | int idx = 0; 68 | for (String v : values) { 69 | set(v, idx); 70 | idx++; 71 | } 72 | } 73 | 74 | public MLChar(String name, int[] dims, int type, int attributes) { 75 | super(name, dims, type, attributes); 76 | chars = new Character[getM() * getN()]; 77 | } 78 | 79 | public void setChar(char ch, int index) { 80 | chars[index] = ch; 81 | } 82 | 83 | /** 84 | * Populates the {@link MLChar} with the {@link String} value. 85 | * @param value the String value 86 | */ 87 | public void set(String value) { 88 | char[] cha = value.toCharArray(); 89 | for (int i = 0; i < getN() && i < value.length(); i++) { 90 | setChar(cha[i], i); 91 | } 92 | } 93 | 94 | /** 95 | * Set one row, specifying the row. 96 | * 97 | * @param value 98 | * @param idx 99 | */ 100 | public void set(String value, int idx) { 101 | int rowOffset = getM(); 102 | for (int i = 0; i < getN(); i++) { 103 | if (i < value.length()) { 104 | setChar(value.charAt(i), idx + (rowOffset * i)); 105 | } else { 106 | setChar(' ', idx + (rowOffset * i)); 107 | } 108 | } 109 | } 110 | 111 | public Character getChar(int m, int n) { 112 | return chars[getIndex(m, n)]; 113 | } 114 | 115 | @SuppressFBWarnings(value = {"EI_EXPOSE_REP"}, justification = "This code is unlikely to be used in a security-sensitive environment.") 116 | public Character[] exportChar() { 117 | return chars; 118 | } 119 | 120 | @Override 121 | public boolean equals(Object o) { 122 | if (o instanceof MLChar) { 123 | return Arrays.equals(chars, ((MLChar) o).chars); 124 | } else { 125 | return false; 126 | } 127 | } 128 | 129 | @Override 130 | public int hashCode() { 131 | return Arrays.hashCode(chars); 132 | } 133 | 134 | /** 135 | * Gets the m-th character matrix's row as String. 136 | * 137 | * @param m - row number 138 | * @return - String 139 | */ 140 | public String getString(int m) { 141 | StringBuffer charbuff = new StringBuffer(); 142 | 143 | for (int n = 0; n < getN(); n++) { 144 | charbuff.append(getChar(m, n)); 145 | } 146 | 147 | return charbuff.toString().trim(); 148 | } 149 | 150 | public String contentToString() { 151 | StringBuffer sb = new StringBuffer(); 152 | sb.append(name + " = \n"); 153 | 154 | for (int m = 0; m < getM(); m++) { 155 | sb.append("\t"); 156 | StringBuffer charbuff = new StringBuffer(); 157 | charbuff.append("'"); 158 | for (int n = 0; n < getN(); n++) { 159 | charbuff.append(getChar(m, n)); 160 | } 161 | charbuff.append("'"); 162 | sb.append(charbuff); 163 | sb.append("\n"); 164 | } 165 | return sb.toString(); 166 | 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLDouble.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.nio.ByteBuffer; 9 | 10 | /** 11 | * Class represents Double array (matrix) 12 | * 13 | * @author Wojciech Gradkowski 14 | */ 15 | public class MLDouble extends MLNumericArray { 16 | 17 | /** 18 | * Normally this constructor is used only by MatFileReader and MatFileWriter 19 | * 20 | * @param name - array name 21 | * @param dims - array dimensions 22 | * @param type - array type: here mxDOUBLE_CLASS 23 | * @param attributes - array flags 24 | */ 25 | public MLDouble(String name, int[] dims, int type, int attributes) { 26 | super(name, dims, type, attributes); 27 | } 28 | 29 | /** 30 | * Create a MLDouble array with given name, 31 | * and dimensions. 32 | * 33 | * @param name - array name 34 | * @param dims - array dimensions 35 | */ 36 | public MLDouble(String name, int[] dims) { 37 | super(name, dims, MLArray.mxDOUBLE_CLASS, 0); 38 | } 39 | 40 | /** 41 | * Jama [math.nist.gov] style: 42 | * construct a 2D real matrix from a one-dimensional packed array 43 | * 44 | * @param name - array name 45 | * @param vals - One-dimensional array of doubles, packed by columns (ala Fortran). 46 | * @param m - Number of rows 47 | */ 48 | public MLDouble(String name, Double[] vals, int m) { 49 | super(name, MLArray.mxDOUBLE_CLASS, vals, m); 50 | } 51 | 52 | /** 53 | * Jama [math.nist.gov] style: 54 | * construct a 2D real matrix from double[][] 55 | * 56 | * Note: array is converted to Double[] 57 | * 58 | * @param name - array name 59 | * @param vals - two-dimensional array of values 60 | */ 61 | public MLDouble(String name, double[][] vals) { 62 | this(name, double2DToDouble(vals), vals.length); 63 | } 64 | 65 | /** 66 | * Jama [math.nist.gov] style: 67 | * construct a matrix from a one-dimensional packed array 68 | * 69 | * @param name - array name 70 | * @param vals - One-dimensional array of doubles, packed by columns (ala Fortran). 71 | * @param m - Number of rows 72 | */ 73 | public MLDouble(String name, double[] vals, int m) { 74 | this(name, castToDouble(vals), m); 75 | } 76 | 77 | /* (non-Javadoc) 78 | * @see ca.mjdsystems.jmatio.types.GenericArrayCreator#createArray(int, int) 79 | */ 80 | public Double[] createArray(int m, int n) { 81 | return new Double[m * n]; 82 | } 83 | 84 | /** 85 | * Gets two-dimensional real array. 86 | * 87 | * @return - 2D real array 88 | */ 89 | public double[][] getArray() { 90 | double[][] result = new double[getM()][]; 91 | 92 | for (int m = 0; m < getM(); m++) { 93 | result[m] = new double[getN()]; 94 | 95 | for (int n = 0; n < getN(); n++) { 96 | result[m][n] = get(m, n); 97 | } 98 | } 99 | return result; 100 | } 101 | 102 | /** 103 | * Casts Double[] to double[] 104 | * 105 | * @param - source Double[] 106 | * @return - result double[] 107 | */ 108 | private static Double[] castToDouble(double[] d) { 109 | Double[] dest = new Double[d.length]; 110 | for (int i = 0; i < d.length; i++) { 111 | dest[i] = (Double) d[i]; 112 | } 113 | return dest; 114 | } 115 | 116 | /** 117 | * Converts double[][] to Double[] 118 | * 119 | * @param dd 120 | * @return 121 | */ 122 | private static Double[] double2DToDouble(double[][] dd) { 123 | Double[] d = new Double[dd.length * dd[0].length]; 124 | for (int n = 0; n < dd[0].length; n++) { 125 | for (int m = 0; m < dd.length; m++) { 126 | d[m + n * dd.length] = dd[m][n]; 127 | } 128 | } 129 | return d; 130 | } 131 | 132 | public int getBytesAllocated() { 133 | return Double.SIZE >> 3; 134 | } 135 | 136 | public Double buldFromBytes(byte[] bytes) { 137 | if (bytes.length != getBytesAllocated()) { 138 | throw new IllegalArgumentException( 139 | "To build from byte array I need array of size: " 140 | + getBytesAllocated()); 141 | } 142 | return ByteBuffer.wrap(bytes).getDouble(); 143 | 144 | } 145 | 146 | public byte[] getByteArray(Double value) { 147 | int byteAllocated = getBytesAllocated(); 148 | ByteBuffer buff = ByteBuffer.allocate(byteAllocated); 149 | buff.putDouble(value); 150 | return buff.array(); 151 | } 152 | 153 | public Class getStorageClazz() { 154 | return Double.class; 155 | } 156 | 157 | @Override 158 | protected Double zero() { 159 | return Zeros.DOUBLE; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLEmptyArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | public class MLEmptyArray extends MLArray { 9 | public MLEmptyArray() { 10 | this(null); 11 | } 12 | 13 | public MLEmptyArray(String name) { 14 | this(name, new int[]{0, 0}, mxDOUBLE_CLASS, 0); 15 | } 16 | 17 | public MLEmptyArray(String name, int[] dims, int type, int attributes) { 18 | super(name, dims, type, attributes); 19 | // TODO Auto-generated constructor stub 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLHandle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | /** 9 | * We have observed a need for this class in a proprietary model. 10 | * It is [not documented in the MAT-File spec](http://stackoverflow.com/questions/36025747/matlab-documentation-on-handle-variables-and-mat-files), 11 | * and we can't figure out how to make it happen ourselves. In 12 | * the testsuite (`TestHandleClass.m` and `handles.mat`) we have 13 | * made our best effort at creating a handle class which triggers 14 | * this code, but these test cases do not actually trigger this code. 15 | * 16 | * Highly experimental until MATLAB releases docs on this behavior. 17 | */ 18 | public class MLHandle extends MLArray { 19 | private final String className; 20 | private final MLCell content; 21 | 22 | public MLHandle(String name, String className, MLCell content) { 23 | super(name, new int[]{1, 1}, MLArray.mxOBJECT_CLASS, 0); 24 | this.className = className; 25 | this.content = content; 26 | } 27 | 28 | public String getClassName() { 29 | return className; 30 | } 31 | 32 | public MLCell getContent() { 33 | return content; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLInt16.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.nio.ByteBuffer; 9 | 10 | /** 11 | * Class represents Int16 array (matrix) 12 | * 13 | */ 14 | public class MLInt16 extends MLNumericArray { 15 | 16 | /** 17 | * Normally this constructor is used only by MatFileReader and MatFileWriter 18 | * 19 | * @param name - array name 20 | * @param dims - array dimensions 21 | * @param type - array type: here mxINT16_CLASS 22 | * @param attributes - array flags 23 | */ 24 | public MLInt16(String name, int[] dims, int type, int attributes) { 25 | super(name, dims, type, attributes); 26 | } 27 | 28 | /** 29 | * Create a MLSingle array with given name, 30 | * and dimensions. 31 | * 32 | * @param name - array name 33 | * @param dims - array dimensions 34 | */ 35 | public MLInt16(String name, int[] dims) { 36 | super(name, dims, MLArray.mxINT16_CLASS, 0); 37 | } 38 | 39 | /** 40 | * Jama [math.nist.gov] style: 41 | * construct a 2D real matrix from a one-dimensional packed array 42 | * 43 | * @param name - array name 44 | * @param vals - One-dimensional array of Short, packed by columns (ala Fortran). 45 | * @param m - Number of rows 46 | */ 47 | public MLInt16(String name, Short[] vals, int m) { 48 | super(name, MLArray.mxINT16_CLASS, vals, m); 49 | } 50 | 51 | /** 52 | * Jama [math.nist.gov] style: 53 | * construct a 2D real matrix from double[][] 54 | * 55 | * Note: array is converted to Short[] 56 | * 57 | * @param name - array name 58 | * @param vals - two-dimensional array of values 59 | */ 60 | public MLInt16(String name, short[][] vals) { 61 | this(name, short2DToShort(vals), vals.length); 62 | } 63 | 64 | /** 65 | * Jama [math.nist.gov] style: 66 | * construct a matrix from a one-dimensional packed array 67 | * 68 | * @param name - array name 69 | * @param vals - One-dimensional array of short, packed by columns (ala Fortran). 70 | * @param m - Number of rows 71 | */ 72 | public MLInt16(String name, short[] vals, int m) { 73 | this(name, castToShort(vals), m); 74 | } 75 | 76 | /* (non-Javadoc) 77 | * @see ca.mjdsystems.jmatio.types.GenericArrayCreator#createArray(int, int) 78 | */ 79 | public Short[] createArray(int m, int n) { 80 | return new Short[m * n]; 81 | } 82 | 83 | /** 84 | * Gets two-dimensional real array. 85 | * 86 | * @return - 2D real array 87 | */ 88 | public short[][] getArray() { 89 | short[][] result = new short[getM()][]; 90 | 91 | for (int m = 0; m < getM(); m++) { 92 | result[m] = new short[getN()]; 93 | 94 | for (int n = 0; n < getN(); n++) { 95 | result[m][n] = getReal(m, n); 96 | } 97 | } 98 | return result; 99 | } 100 | 101 | /** 102 | * Casts Short[] to short[] 103 | * 104 | * @param - source short[] 105 | * @return - result Short[] 106 | */ 107 | private static Short[] castToShort(short[] d) { 108 | Short[] dest = new Short[d.length]; 109 | for (int i = 0; i < d.length; i++) { 110 | dest[i] = (Short) d[i]; 111 | } 112 | return dest; 113 | } 114 | 115 | /** 116 | * Converts short[][] to Short[] 117 | * 118 | * @param dd 119 | * @return 120 | */ 121 | private static Short[] short2DToShort(short[][] dd) { 122 | Short[] d = new Short[dd.length * dd[0].length]; 123 | for (int n = 0; n < dd[0].length; n++) { 124 | for (int m = 0; m < dd.length; m++) { 125 | d[m + n * dd.length] = dd[m][n]; 126 | } 127 | } 128 | return d; 129 | } 130 | 131 | public int getBytesAllocated() { 132 | return Short.SIZE >> 3; 133 | } 134 | 135 | public Short buldFromBytes(byte[] bytes) { 136 | if (bytes.length != getBytesAllocated()) { 137 | throw new IllegalArgumentException( 138 | "To build from byte array I need array of size: " 139 | + getBytesAllocated()); 140 | } 141 | return ByteBuffer.wrap(bytes).getShort(); 142 | 143 | } 144 | 145 | public byte[] getByteArray(Short value) { 146 | int byteAllocated = getBytesAllocated(); 147 | ByteBuffer buff = ByteBuffer.allocate(byteAllocated); 148 | buff.putShort(value); 149 | return buff.array(); 150 | } 151 | 152 | public Class getStorageClazz() { 153 | return Short.class; 154 | } 155 | 156 | @Override 157 | protected Short zero() { 158 | return Zeros.SHORT; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLInt32.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.nio.ByteBuffer; 9 | 10 | public class MLInt32 extends MLNumericArray { 11 | 12 | /** 13 | * Normally this constructor is used only by MatFileReader and MatFileWriter 14 | * 15 | * @param name - array name 16 | * @param dims - array dimensions 17 | * @param type - array type: here mxDOUBLE_CLASS 18 | * @param attributes - array flags 19 | */ 20 | public MLInt32(String name, int[] dims, int type, int attributes) { 21 | super(name, dims, type, attributes); 22 | } 23 | 24 | /** 25 | * Create a {@link MLInt64} array with given name, 26 | * and dimensions. 27 | * 28 | * @param name - array name 29 | * @param dims - array dimensions 30 | */ 31 | public MLInt32(String name, int[] dims) { 32 | super(name, dims, MLArray.mxINT32_CLASS, 0); 33 | } 34 | 35 | /** 36 | * Jama [math.nist.gov] style: 37 | * construct a 2D real matrix from a one-dimensional packed array 38 | * 39 | * @param name - array name 40 | * @param vals - One-dimensional array of doubles, packed by columns (ala Fortran). 41 | * @param m - Number of rows 42 | */ 43 | public MLInt32(String name, Integer[] vals, int m) { 44 | super(name, MLArray.mxINT32_CLASS, vals, m); 45 | } 46 | 47 | /** 48 | * Jama [math.nist.gov] style: 49 | * construct a 2D real matrix from byte[][] 50 | * 51 | * Note: array is converted to Byte[] 52 | * 53 | * @param name - array name 54 | * @param vals - two-dimensional array of values 55 | */ 56 | public MLInt32(String name, int[][] vals) { 57 | this(name, int2DToInteger(vals), vals.length); 58 | } 59 | 60 | /** 61 | * Jama [math.nist.gov] style: 62 | * construct a matrix from a one-dimensional packed array 63 | * 64 | * @param name - array name 65 | * @param vals - One-dimensional array of doubles, packed by columns (ala Fortran). 66 | * @param m - Number of rows 67 | */ 68 | public MLInt32(String name, int[] vals, int m) { 69 | this(name, castToInteger(vals), m); 70 | } 71 | 72 | /* (non-Javadoc) 73 | * @see ca.mjdsystems.jmatio.types.GenericArrayCreator#createArray(int, int) 74 | */ 75 | public Integer[] createArray(int m, int n) { 76 | return new Integer[m * n]; 77 | } 78 | 79 | /** 80 | * Gets two-dimensional real array. 81 | * 82 | * @return - 2D real array 83 | */ 84 | public int[][] getArray() { 85 | int[][] result = new int[getM()][]; 86 | 87 | for (int m = 0; m < getM(); m++) { 88 | result[m] = new int[getN()]; 89 | 90 | for (int n = 0; n < getN(); n++) { 91 | result[m][n] = get(m, n); 92 | } 93 | } 94 | return result; 95 | } 96 | 97 | /** 98 | * Casts Double[] to byte[] 99 | * 100 | * @param - source Long[] 101 | * @return - result long[] 102 | */ 103 | private static Integer[] castToInteger(int[] d) { 104 | Integer[] dest = new Integer[d.length]; 105 | for (int i = 0; i < d.length; i++) { 106 | dest[i] = d[i]; 107 | } 108 | return dest; 109 | } 110 | 111 | /** 112 | * Converts byte[][] to Long[] 113 | * 114 | * @param dd 115 | * @return 116 | */ 117 | private static Integer[] int2DToInteger(int[][] dd) { 118 | Integer[] d = new Integer[dd.length * dd[0].length]; 119 | for (int n = 0; n < dd[0].length; n++) { 120 | for (int m = 0; m < dd.length; m++) { 121 | d[m + n * dd.length] = dd[m][n]; 122 | } 123 | } 124 | return d; 125 | } 126 | 127 | public Integer buldFromBytes(byte[] bytes) { 128 | if (bytes.length != getBytesAllocated()) { 129 | throw new IllegalArgumentException( 130 | "To build from byte array I need array of size: " 131 | + getBytesAllocated()); 132 | } 133 | return ByteBuffer.wrap(bytes).getInt(); 134 | } 135 | 136 | public int getBytesAllocated() { 137 | return Integer.SIZE >> 3; 138 | } 139 | 140 | public Class getStorageClazz() { 141 | return Integer.class; 142 | } 143 | 144 | public byte[] getByteArray(Integer value) { 145 | int byteAllocated = getBytesAllocated(); 146 | ByteBuffer buff = ByteBuffer.allocate(byteAllocated); 147 | buff.putInt(value); 148 | return buff.array(); 149 | } 150 | 151 | @Override 152 | protected Integer zero() { 153 | return Zeros.INTEGER; 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLInt64.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.nio.ByteBuffer; 9 | 10 | /** 11 | * Class represents Int64 (long) array (matrix) 12 | * 13 | * @author Wojciech Gradkowski 14 | */ 15 | public class MLInt64 extends MLNumericArray { 16 | 17 | /** 18 | * Normally this constructor is used only by MatFileReader and MatFileWriter 19 | * 20 | * @param name - array name 21 | * @param dims - array dimensions 22 | * @param type - array type: here mxDOUBLE_CLASS 23 | * @param attributes - array flags 24 | */ 25 | public MLInt64(String name, int[] dims, int type, int attributes) { 26 | super(name, dims, type, attributes); 27 | } 28 | 29 | /** 30 | * Create a {@link MLInt64} array with given name, 31 | * and dimensions. 32 | * 33 | * @param name - array name 34 | * @param dims - array dimensions 35 | */ 36 | public MLInt64(String name, int[] dims) { 37 | super(name, dims, MLArray.mxINT64_CLASS, 0); 38 | } 39 | 40 | /** 41 | * Jama [math.nist.gov] style: 42 | * construct a 2D real matrix from a one-dimensional packed array 43 | * 44 | * @param name - array name 45 | * @param vals - One-dimensional array of doubles, packed by columns (ala Fortran). 46 | * @param m - Number of rows 47 | */ 48 | public MLInt64(String name, Long[] vals, int m) { 49 | super(name, MLArray.mxINT64_CLASS, vals, m); 50 | } 51 | 52 | /** 53 | * Jama [math.nist.gov] style: 54 | * construct a 2D real matrix from byte[][] 55 | * 56 | * Note: array is converted to Byte[] 57 | * 58 | * @param name - array name 59 | * @param vals - two-dimensional array of values 60 | */ 61 | public MLInt64(String name, long[][] vals) { 62 | this(name, long2DToLong(vals), vals.length); 63 | } 64 | 65 | /** 66 | * Jama [math.nist.gov] style: 67 | * construct a matrix from a one-dimensional packed array 68 | * 69 | * @param name - array name 70 | * @param vals - One-dimensional array of doubles, packed by columns (ala Fortran). 71 | * @param m - Number of rows 72 | */ 73 | public MLInt64(String name, long[] vals, int m) { 74 | this(name, castToLong(vals), m); 75 | } 76 | 77 | /* (non-Javadoc) 78 | * @see ca.mjdsystems.jmatio.types.GenericArrayCreator#createArray(int, int) 79 | */ 80 | public Long[] createArray(int m, int n) { 81 | return new Long[m * n]; 82 | } 83 | 84 | /** 85 | * Gets two-dimensional real array. 86 | * 87 | * @return - 2D real array 88 | */ 89 | public long[][] getArray() { 90 | long[][] result = new long[getM()][]; 91 | 92 | for (int m = 0; m < getM(); m++) { 93 | result[m] = new long[getN()]; 94 | 95 | for (int n = 0; n < getN(); n++) { 96 | result[m][n] = getReal(m, n); 97 | } 98 | } 99 | return result; 100 | } 101 | 102 | /** 103 | * Casts Double[] to byte[] 104 | * 105 | * @param - source Long[] 106 | * @return - result long[] 107 | */ 108 | private static Long[] castToLong(long[] d) { 109 | Long[] dest = new Long[d.length]; 110 | for (int i = 0; i < d.length; i++) { 111 | dest[i] = (long) d[i]; 112 | } 113 | return dest; 114 | } 115 | 116 | /** 117 | * Converts byte[][] to Long[] 118 | * 119 | * @param dd 120 | * @return 121 | */ 122 | private static Long[] long2DToLong(long[][] dd) { 123 | Long[] d = new Long[dd.length * dd[0].length]; 124 | for (int n = 0; n < dd[0].length; n++) { 125 | for (int m = 0; m < dd.length; m++) { 126 | d[m + n * dd.length] = dd[m][n]; 127 | } 128 | } 129 | return d; 130 | } 131 | 132 | public Long buldFromBytes(byte[] bytes) { 133 | if (bytes.length != getBytesAllocated()) { 134 | throw new IllegalArgumentException( 135 | "To build from byte array I need array of size: " 136 | + getBytesAllocated()); 137 | } 138 | return ByteBuffer.wrap(bytes).getLong(); 139 | } 140 | 141 | public int getBytesAllocated() { 142 | return Long.SIZE >> 3; 143 | } 144 | 145 | public Class getStorageClazz() { 146 | return Long.class; 147 | } 148 | 149 | public byte[] getByteArray(Long value) { 150 | int byteAllocated = getBytesAllocated(); 151 | ByteBuffer buff = ByteBuffer.allocate(byteAllocated); 152 | buff.putLong(value); 153 | return buff.array(); 154 | } 155 | 156 | @Override 157 | protected Long zero() { 158 | return Zeros.LONG; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLInt8.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.nio.ByteBuffer; 9 | 10 | public class MLInt8 extends MLNumericArray { 11 | /** 12 | * Normally this constructor is used only by MatFileReader and MatFileWriter 13 | * 14 | * @param name - array name 15 | * @param dims - array dimensions 16 | * @param type - array type: here mxDOUBLE_CLASS 17 | * @param attributes - array flags 18 | */ 19 | public MLInt8(String name, int[] dims, int type, int attributes) { 20 | super(name, dims, type, attributes); 21 | } 22 | 23 | /** 24 | * Create a {@link MLUInt8} array with given name, 25 | * and dimensions. 26 | * 27 | * @param name - array name 28 | * @param dims - array dimensions 29 | */ 30 | public MLInt8(String name, int[] dims) { 31 | super(name, dims, MLArray.mxINT8_CLASS, 0); 32 | } 33 | 34 | /** 35 | * Jama [math.nist.gov] style: 36 | * construct a 2D real matrix from a one-dimensional packed array 37 | * 38 | * @param name - array name 39 | * @param vals - One-dimensional array of doubles, packed by columns (ala Fortran). 40 | * @param m - Number of rows 41 | */ 42 | public MLInt8(String name, Byte[] vals, int m) { 43 | super(name, MLArray.mxINT8_CLASS, vals, m); 44 | } 45 | 46 | /** 47 | * Jama [math.nist.gov] style: 48 | * construct a 2D real matrix from byte[][] 49 | * 50 | * Note: array is converted to Byte[] 51 | * 52 | * @param name - array name 53 | * @param vals - two-dimensional array of values 54 | */ 55 | public MLInt8(String name, byte[][] vals) { 56 | this(name, byte2DToByte(vals), vals.length); 57 | } 58 | 59 | /** 60 | * Jama [math.nist.gov] style: 61 | * construct a matrix from a one-dimensional packed array 62 | * 63 | * @param name - array name 64 | * @param vals - One-dimensional array of doubles, packed by columns (ala Fortran). 65 | * @param m - Number of rows 66 | */ 67 | public MLInt8(String name, byte[] vals, int m) { 68 | this(name, castToByte(vals), m); 69 | } 70 | 71 | /* (non-Javadoc) 72 | * @see ca.mjdsystems.jmatio.types.GenericArrayCreator#createArray(int, int) 73 | */ 74 | public Byte[] createArray(int m, int n) { 75 | return new Byte[m * n]; 76 | } 77 | 78 | /** 79 | * Gets two-dimensional real array. 80 | * 81 | * @return - 2D real array 82 | */ 83 | public byte[][] getArray() { 84 | byte[][] result = new byte[getM()][]; 85 | 86 | for (int m = 0; m < getM(); m++) { 87 | result[m] = new byte[getN()]; 88 | 89 | for (int n = 0; n < getN(); n++) { 90 | result[m][n] = getReal(m, n); 91 | } 92 | } 93 | return result; 94 | } 95 | 96 | /** 97 | * Casts Double[] to byte[] 98 | * 99 | * @param - source Byte[] 100 | * @return - result byte[] 101 | */ 102 | private static Byte[] castToByte(byte[] d) { 103 | Byte[] dest = new Byte[d.length]; 104 | for (int i = 0; i < d.length; i++) { 105 | dest[i] = (byte) d[i]; 106 | } 107 | return dest; 108 | } 109 | 110 | /** 111 | * Converts byte[][] to Byte[] 112 | * 113 | * @param dd 114 | * @return 115 | */ 116 | private static Byte[] byte2DToByte(byte[][] dd) { 117 | Byte[] d = new Byte[dd.length * dd[0].length]; 118 | for (int n = 0; n < dd[0].length; n++) { 119 | for (int m = 0; m < dd.length; m++) { 120 | d[m + n * dd.length] = dd[m][n]; 121 | } 122 | } 123 | return d; 124 | } 125 | 126 | public Byte buldFromBytes(byte[] bytes) { 127 | if (bytes.length != getBytesAllocated()) { 128 | throw new IllegalArgumentException( 129 | "To build from byte array I need array of size: " 130 | + getBytesAllocated()); 131 | } 132 | return bytes[0]; 133 | } 134 | 135 | public byte[] getByteArray(Byte value) { 136 | return new byte[]{value}; 137 | } 138 | 139 | public int getBytesAllocated() { 140 | return Byte.SIZE >> 3; 141 | } 142 | 143 | public Class getStorageClazz() { 144 | return Byte.class; 145 | } 146 | 147 | /** 148 | * Override to accelerate the performance 149 | * 150 | * @see com.jmatio.types.MLNumericArray#_get(java.nio.ByteBuffer, int) 151 | */ 152 | @Override 153 | protected Byte _get(ByteBuffer buffer, int index) { 154 | return buffer.get(index); 155 | } 156 | 157 | @Override 158 | protected Byte zero() { 159 | return Zeros.BYTE; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLJavaObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.io.ObjectInputStream; 9 | import java.nio.ByteBuffer; 10 | 11 | import com.jmatio.io.stream.ByteBufferInputStream; 12 | 13 | @SuppressWarnings("rawtypes") 14 | public class MLJavaObject extends MLArray { 15 | 16 | private final String className; 17 | private final MLNumericArray content; 18 | 19 | public MLJavaObject(String name, String className, MLNumericArray content) { 20 | super(name, new int[]{1, 1}, MLArray.mxOPAQUE_CLASS, 0); 21 | 22 | this.className = className; 23 | this.content = content; 24 | } 25 | 26 | public String getClassName() { 27 | return className; 28 | } 29 | 30 | public ByteBuffer getContent() { 31 | return content.getRealByteBuffer(); 32 | } 33 | 34 | /** Attempts to instantiate the Java Object, and all kinds of stuff can go wrong. */ 35 | public Object instantiateObject() throws Exception { 36 | // de-serialize object 37 | ObjectInputStream ois = new ObjectInputStream( 38 | new ByteBufferInputStream(content.getRealByteBuffer(), content.getRealByteBuffer().limit())); 39 | try { 40 | return ois.readObject(); 41 | } finally { 42 | ois.close(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLNumericArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.nio.ByteBuffer; 9 | import java.util.Arrays; 10 | 11 | /** 12 | * Abstract class for numeric arrays. 13 | * 14 | * @author Wojciech Gradkowski 15 | * 16 | * @param 17 | */ 18 | /** 19 | * @author Wojciech Gradkowski 20 | * 21 | * @param 22 | */ 23 | public abstract class MLNumericArray extends MLArray implements 24 | ByteStorageSupport { 25 | private ByteBuffer real; 26 | private ByteBuffer imaginary; 27 | /** The buffer for creating Number from bytes */ 28 | private byte[] bytes; 29 | 30 | /** 31 | * Normally this constructor is used only by MatFileReader and MatFileWriter 32 | * 33 | * @param name - array name 34 | * @param dims - array dimensions 35 | * @param type - array type 36 | * @param attributes - array flags 37 | */ 38 | public MLNumericArray(String name, int[] dims, int type, int attributes) { 39 | super(name, dims, type, attributes); 40 | allocate(); 41 | } 42 | 43 | protected void allocate() { 44 | real = ByteBuffer.allocate(getSize() * getBytesAllocated()); 45 | if (isComplex()) { 46 | imaginary = ByteBuffer.allocate(getSize() * getBytesAllocated()); 47 | } 48 | bytes = new byte[getBytesAllocated()]; 49 | } 50 | 51 | /** Returns the value of "zero" for this type of array. */ 52 | protected abstract T zero(); 53 | 54 | /** 55 | * Jama [math.nist.gov] style: 56 | * construct a 2D real matrix from a one-dimensional packed array 57 | * 58 | * @param name - array name 59 | * @param type - array type 60 | * @param vals - One-dimensional array of doubles, packed by columns (ala Fortran). 61 | * @param m - Number of rows 62 | */ 63 | public MLNumericArray(String name, int type, T[] vals, int m) { 64 | this(name, new int[]{m, vals.length / m}, type, 0); 65 | //fill the array 66 | for (int i = 0; i < vals.length; i++) { 67 | set(vals[i], i); 68 | } 69 | } 70 | 71 | /** Gets a single real array element. */ 72 | public T getReal(int index) { 73 | return _get(real, index); 74 | } 75 | 76 | /** Gets a single real array element. */ 77 | public T getReal(int m, int n) { 78 | return getReal(getIndex(m, n)); 79 | } 80 | 81 | /** Gets a single real array element. */ 82 | public T getReal(int... indices) { 83 | return getReal(getIndex(indices)); 84 | } 85 | 86 | /** Sets a single real array element. */ 87 | public void setReal(T value, int index) { 88 | _set(real, value, index); 89 | } 90 | 91 | /** Sets a single real array element. */ 92 | public void setReal(T value, int m, int n) { 93 | setReal(value, getIndex(m, n)); 94 | } 95 | 96 | /** Sets a single real array element. */ 97 | public void setReal(T value, int... indices) { 98 | setReal(value, getIndex(indices)); 99 | } 100 | 101 | /** Sets real part of a matrix. */ 102 | public void setReal(T[] vector) { 103 | if (vector.length != getSize()) { 104 | throw new IllegalArgumentException("Matrix dimensions do not match. " + getSize() + " not " + vector.length); 105 | } 106 | System.arraycopy(vector, 0, real, 0, vector.length); 107 | } 108 | 109 | /** Sets a single imaginary array element. */ 110 | public void setImaginary(T value, int index) { 111 | assertComplex(); 112 | _set(imaginary, value, index); 113 | } 114 | 115 | /** Sets a single imaginary array element. */ 116 | public void setImaginary(T value, int m, int n) { 117 | setImaginary(value, getIndex(m, n)); 118 | } 119 | 120 | /** Sets a single imaginary array element. */ 121 | public void setImaginary(T value, int... indices) { 122 | setImaginary(value, getIndex(indices)); 123 | } 124 | 125 | /** Returns the imaginary value at the given index, always 0 for non-complex arrays. */ 126 | public T getImaginary(int index) { 127 | if (isComplex()) { 128 | return _get(imaginary, index); 129 | } else { 130 | return zero(); 131 | } 132 | } 133 | 134 | /** Returns the imaginary value at the given index. */ 135 | public T getImaginary(int m, int n) { 136 | return getImaginary(getIndex(m, n)); 137 | } 138 | 139 | /** Returns the imaginary value at the given index. */ 140 | public T getImaginary(int... indices) { 141 | return getImaginary(getIndex(indices)); 142 | } 143 | 144 | protected void assertComplex() { 145 | if (!isComplex()) { 146 | throw new UnsupportedOperationException("Cannot use this method for non-Complex matrices"); 147 | } 148 | } 149 | 150 | /** Sets the value at the given index for non-complex arrays. */ 151 | public void set(T value, int index) { 152 | setReal(value, index); 153 | } 154 | 155 | /** Sets the value at the given index for non-complex arrays. */ 156 | public void set(T value, int m, int n) { 157 | set(value, getIndex(m, n)); 158 | } 159 | 160 | /** Sets the value at the given index for non-complex arrays. */ 161 | public void set(T value, int... indices) { 162 | set(value, getIndex(indices)); 163 | } 164 | 165 | /** Returns the value at the given index for non-complex arrays. */ 166 | public T get(int index) { 167 | return getReal(index); 168 | } 169 | 170 | /** Returns the value at the given index for non-complex arrays. */ 171 | public T get(int m, int n) { 172 | return get(getIndex(m, n)); 173 | } 174 | 175 | /** Returns the value at the given index for non-complex arrays. */ 176 | public T get(int... indices) { 177 | return get(getIndex(indices)); 178 | } 179 | 180 | /** Sets the content of this entire array for non-complex arrays. */ 181 | public void set(T[] vector) { 182 | if (vector.length != getSize()) { 183 | throw new IllegalArgumentException("Matrix dimensions do not match. " + getSize() + " not " + vector.length); 184 | } 185 | System.arraycopy(vector, 0, real, 0, vector.length); 186 | } 187 | 188 | private int getByteOffset(int index) { 189 | return index * getBytesAllocated(); 190 | } 191 | 192 | protected T _get(ByteBuffer buffer, int index) { 193 | buffer.position(getByteOffset(index)); 194 | buffer.get(bytes, 0, bytes.length); 195 | return buldFromBytes(bytes); 196 | } 197 | 198 | protected void _set(ByteBuffer buffer, T value, int index) { 199 | buffer.position(getByteOffset(index)); 200 | buffer.put(getByteArray(value)); 201 | } 202 | 203 | public void putImaginaryByteBuffer(ByteBuffer buff) { 204 | if (!isComplex()) { 205 | throw new RuntimeException("Array is not complex"); 206 | } 207 | imaginary.rewind(); 208 | imaginary.put(buff); 209 | } 210 | 211 | public ByteBuffer getImaginaryByteBuffer() { 212 | return imaginary; 213 | } 214 | 215 | public void putRealByteBuffer(ByteBuffer buff) { 216 | real.rewind(); 217 | real.put(buff); 218 | } 219 | 220 | public ByteBuffer getRealByteBuffer() { 221 | return real; 222 | } 223 | 224 | @Override 225 | public String contentToString() { 226 | if (getSize() > 1000) { 227 | return "Cannot display variables with more than 1000 elements."; 228 | } 229 | StringBuilder sb = new StringBuilder(); 230 | for (int m = 0; m < getM(); m++) { 231 | for (int n = 0; n < getN(); n++) { 232 | sb.append(getReal(m, n)); 233 | if (isComplex()) { 234 | sb.append("+" + getImaginary(m, n)); 235 | } 236 | sb.append("\t"); 237 | } 238 | sb.append("\n"); 239 | } 240 | // don't let it end in \t\n 241 | if (sb.length() > 2) { 242 | sb.setLength(sb.length() - 2); 243 | } 244 | return sb.toString(); 245 | } 246 | 247 | @Override 248 | public boolean equals(Object o) { 249 | if (o instanceof MLNumericArray) { 250 | boolean result = directByteBufferEquals(real, ((MLNumericArray) o).real) 251 | && Arrays.equals(dims, ((MLNumericArray) o).dims); 252 | if (isComplex() && result) { 253 | result &= directByteBufferEquals(imaginary, ((MLNumericArray) o).imaginary); 254 | } 255 | return result; 256 | } 257 | return super.equals(o); 258 | } 259 | 260 | @Override 261 | public int hashCode() { 262 | if (isComplex()) { 263 | return Arrays.hashCode(new Object[]{real, dims, imaginary}); 264 | } else { 265 | return Arrays.hashCode(new Object[]{real, dims}); 266 | } 267 | } 268 | 269 | /** 270 | * Equals implementation for direct ByteBuffer 271 | * 272 | * @param buffa the source buffer to be compared 273 | * @param buffb the destination buffer to be compared 274 | * @return true if buffers are equal in terms of content 275 | */ 276 | private static boolean directByteBufferEquals(ByteBuffer buffa, ByteBuffer buffb) { 277 | if (buffa == buffb) { 278 | return true; 279 | } 280 | 281 | if (buffa == null || buffb == null) { 282 | return false; 283 | } 284 | 285 | buffa.rewind(); 286 | buffb.rewind(); 287 | 288 | int length = buffa.remaining(); 289 | 290 | if (buffb.remaining() != length) { 291 | return false; 292 | } 293 | 294 | for (int i = 0; i < length; i++) { 295 | if (buffa.get() != buffb.get()) { 296 | return false; 297 | } 298 | } 299 | 300 | return true; 301 | } 302 | 303 | public void dispose() { 304 | if (real != null) { 305 | real.clear(); 306 | } 307 | if (imaginary != null) { 308 | real.clear(); 309 | } 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.util.Map; 9 | 10 | import com.jmatio.common.DeterministicKeyMap; 11 | 12 | /** 13 | * This class represents Matlab's Object object (object array). 14 | * 15 | * Note: array of structures can contain only structures of the same type 16 | * , that means structures that have the same field names. 17 | * 18 | * @author Wojciech Gradkowski 19 | */ 20 | public class MLObject extends MLStructureObjectBase { 21 | private String className; 22 | 23 | public MLObject(String name, String className, int[] dimensions, int attributes) { 24 | super(name, dimensions, MLArray.mxOBJECT_CLASS, 0); 25 | this.className = className; 26 | } 27 | 28 | public String getClassName() { 29 | return className; 30 | } 31 | 32 | public void setFields(int i, Map structure) { 33 | keys.addAll(structure.keySet()); 34 | mlStructArray.put(i, new DeterministicKeyMap(keys, structure)); 35 | } 36 | 37 | /** Only used by {@link com.jmatio.io.MLObjectPlaceholder}. */ 38 | protected void copyFrom(MLObject obj) { 39 | this.className = obj.className; 40 | this.keys = obj.keys; 41 | this.mlStructArray = obj.mlStructArray; 42 | this.currentIndex = obj.currentIndex; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLSingle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.nio.ByteBuffer; 9 | 10 | public class MLSingle extends MLNumericArray { 11 | 12 | public MLSingle(String name, Float[] vals, int m) { 13 | super(name, MLArray.mxSINGLE_CLASS, vals, m); 14 | } 15 | 16 | public MLSingle(String name, int[] dims, int type, int attributes) { 17 | super(name, dims, type, attributes); 18 | } 19 | 20 | public Float[] createArray(int m, int n) { 21 | return new Float[m * n]; 22 | } 23 | 24 | public Float buldFromBytes(byte[] bytes) { 25 | if (bytes.length != getBytesAllocated()) { 26 | throw new IllegalArgumentException( 27 | "To build from byte array I need array of size: " 28 | + getBytesAllocated()); 29 | } 30 | return ByteBuffer.wrap(bytes).getFloat(); 31 | } 32 | 33 | public byte[] getByteArray(Float value) { 34 | int byteAllocated = getBytesAllocated(); 35 | ByteBuffer buff = ByteBuffer.allocate(byteAllocated); 36 | buff.putFloat(value); 37 | return buff.array(); 38 | } 39 | 40 | public int getBytesAllocated() { 41 | return Float.SIZE >> 3; 42 | } 43 | 44 | public Class getStorageClazz() { 45 | return Float.class; 46 | } 47 | 48 | @Override 49 | protected Float zero() { 50 | return Zeros.FLOAT; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLSparse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.nio.ByteBuffer; 9 | import java.util.Arrays; 10 | import java.util.SortedMap; 11 | import java.util.SortedSet; 12 | import java.util.TreeMap; 13 | import java.util.TreeSet; 14 | 15 | public class MLSparse extends MLNumericArray { 16 | int nzmax; 17 | private SortedSet indexSet; 18 | private SortedMap real; 19 | private SortedMap imaginary; 20 | 21 | /** 22 | * @param name 23 | * @param dims 24 | * @param attributes 25 | * @param nzmax 26 | */ 27 | public MLSparse(String name, int[] dims, int attributes, int nzmax) { 28 | super(name, dims, MLArray.mxSPARSE_CLASS, attributes); 29 | this.nzmax = nzmax; 30 | } 31 | 32 | @Override 33 | protected void allocate() { 34 | indexSet = new TreeSet(); 35 | real = new TreeMap(); 36 | if (isComplex()) { 37 | imaginary = new TreeMap(); 38 | } else { 39 | imaginary = null; 40 | } 41 | } 42 | 43 | /** 44 | * Gets maximum number of non-zero values 45 | * 46 | * @return 47 | */ 48 | public int getMaxNZ() { 49 | return nzmax; 50 | } 51 | 52 | /** 53 | * Gets row indices 54 | * 55 | * ir points to an integer array of length nzmax containing the row indices of 56 | * the corresponding elements in pr and pi. 57 | */ 58 | public int[] getIR() { 59 | int[] ir = new int[nzmax]; 60 | int i = 0; 61 | for (IndexMN index : indexSet) { 62 | ir[i++] = index.m; 63 | } 64 | return ir; 65 | } 66 | 67 | /** 68 | * Gets column indices 69 | * 70 | * ic points to an integer array of length nzmax containing the column indices of 71 | * the corresponding elements in pr and pi. 72 | */ 73 | public int[] getIC() { 74 | int[] ic = new int[nzmax]; 75 | int i = 0; 76 | for (IndexMN index : indexSet) { 77 | ic[i++] = index.n; 78 | } 79 | return ic; 80 | } 81 | 82 | /** 83 | * Gets column indices. 84 | * 85 | * jc points to an integer array of length N+1 that contains column index information. 86 | * For j, in the range 0<=j<=N, jc[j] is the index in ir and pr (and pi 87 | * if it exists) of the first nonzero entry in the jth column and jc[j+1]?????????1 index 88 | * of the last nonzero entry. As a result, jc[N] is also equal to nnz, the number 89 | * of nonzero entries in the matrix. If nnz is less than nzmax, then more nonzero 90 | * entries can be inserted in the array without allocating additional storage 91 | * 92 | * @return 93 | */ 94 | public int[] getJC() { 95 | int[] jc = new int[getN() + 1]; 96 | // jc[j] is the number of nonzero elements in all preceeding columns 97 | for (IndexMN index : indexSet) { 98 | for (int column = index.n + 1; column < jc.length; column++) { 99 | jc[column]++; 100 | } 101 | } 102 | return jc; 103 | } 104 | 105 | @Override 106 | public Double getReal(int m, int n) { 107 | IndexMN i = new IndexMN(m, n); 108 | Double result = real.get(i); 109 | return result == null ? Zeros.DOUBLE : result; 110 | } 111 | 112 | @Override 113 | public Double getReal(int index) { 114 | throw new UnsupportedOperationException("Can't get Sparse array elements by index. " + 115 | "Please use getReal(int m, int n) instead."); 116 | } 117 | 118 | @Override 119 | public void setReal(Double value, int m, int n) { 120 | IndexMN i = new IndexMN(m, n); 121 | indexSet.add(i); 122 | real.put(i, value); 123 | } 124 | 125 | @Override 126 | public void setReal(Double value, int index) { 127 | throw new UnsupportedOperationException("Can't set Sparse array elements by index. " + 128 | "Please use setReal(Double value, int m, int n) instead."); 129 | } 130 | 131 | @Override 132 | public void setImaginary(Double value, int m, int n) { 133 | assertComplex(); 134 | IndexMN i = new IndexMN(m, n); 135 | indexSet.add(i); 136 | imaginary.put(i, value); 137 | } 138 | 139 | @Override 140 | public void setImaginary(Double value, int index) { 141 | throw new IllegalArgumentException("Can't set Sparse array elements by index. " + 142 | "Please use setImaginary(Double value, int m, int n) instead."); 143 | } 144 | 145 | @Override 146 | public Double getImaginary(int m, int n) { 147 | IndexMN i = new IndexMN(m, n); 148 | Double result = imaginary.get(i); 149 | return result == null ? Zeros.DOUBLE : result; 150 | } 151 | 152 | @Override 153 | public Double getImaginary(int index) { 154 | throw new IllegalArgumentException("Can't get Sparse array elements by index. " + 155 | "Please use getImaginary(int index) instead."); 156 | } 157 | 158 | @Override 159 | public void set(Double value, int m, int n) { 160 | IndexMN i = new IndexMN(m, n); 161 | indexSet.add(i); 162 | real.put(i, value); 163 | } 164 | 165 | @Override 166 | public void set(Double value, int index) { 167 | throw new IllegalArgumentException("Can't set Sparse array elements by index. " + 168 | "Please use setImaginary(Double value, int m, int n) instead."); 169 | } 170 | 171 | @Override 172 | public Double get(int m, int n) { 173 | IndexMN i = new IndexMN(m, n); 174 | Double result = real.get(i); 175 | return result == null ? Zeros.DOUBLE : result; 176 | } 177 | 178 | @Override 179 | public Double get(int index) { 180 | throw new IllegalArgumentException("Can't get Sparse array elements by index. " + 181 | "Please use getImaginary(int index) instead."); 182 | } 183 | 184 | /** 185 | * Returns the real part (PR) array. PR has length number-of-nonzero-values. 186 | * 187 | * @return real part 188 | */ 189 | public Double[] exportReal() { 190 | Double[] ad = new Double[indexSet.size()]; 191 | int i = 0; 192 | for (IndexMN index : indexSet) { 193 | if (real.containsKey(index)) { 194 | ad[i] = real.get(index); 195 | } else { 196 | ad[i] = Zeros.DOUBLE; 197 | } 198 | i++; 199 | } 200 | return ad; 201 | } 202 | 203 | /** 204 | * Returns the imaginary part (PI) array. PI has length number-of-nonzero-values. 205 | * 206 | * @return 207 | */ 208 | public Double[] exportImaginary() { 209 | Double[] ad = new Double[indexSet.size()]; 210 | int i = 0; 211 | for (IndexMN index : indexSet) { 212 | if (imaginary.containsKey(index)) { 213 | ad[i] = imaginary.get(index); 214 | } else { 215 | ad[i] = Zeros.DOUBLE; 216 | } 217 | i++; 218 | } 219 | return ad; 220 | } 221 | 222 | /* (non-Javadoc) 223 | * @see com.paradigmdesigner.matlab.types.MLArray#contentToString() 224 | */ 225 | @Override 226 | public String contentToString() { 227 | StringBuffer sb = new StringBuffer(); 228 | sb.append(name + " = \n"); 229 | 230 | for (IndexMN i : indexSet) { 231 | sb.append("\t("); 232 | sb.append(i.m + "," + i.n); 233 | sb.append(")"); 234 | sb.append("\t" + getReal(i.m, i.n)); 235 | if (isComplex()) { 236 | sb.append("+" + getImaginary(i.m, i.n)); 237 | } 238 | sb.append("\n"); 239 | 240 | } 241 | 242 | return sb.toString(); 243 | } 244 | 245 | /** 246 | * Matrix index (m,n) 247 | * 248 | * @author Wojciech Gradkowski 249 | */ 250 | private class IndexMN implements Comparable { 251 | int m; 252 | int n; 253 | 254 | public IndexMN(int m, int n) { 255 | this.m = m; 256 | this.n = n; 257 | } 258 | 259 | /* (non-Javadoc) 260 | * @see java.lang.Comparable#compareTo(java.lang.Object) 261 | */ 262 | @Override 263 | public int compareTo(IndexMN anOtherIndex) { 264 | return getIndex(m, n) - getIndex(anOtherIndex.m, anOtherIndex.n); 265 | } 266 | 267 | /* (non-Javadoc) 268 | * @see java.lang.Object#equals(java.lang.Object) 269 | */ 270 | @Override 271 | public boolean equals(Object o) { 272 | if (o instanceof IndexMN) { 273 | return m == ((IndexMN) o).m && n == ((IndexMN) o).n; 274 | } 275 | return super.equals(o); 276 | } 277 | 278 | @Override 279 | public int hashCode() { 280 | return Arrays.hashCode(new int[]{m, n}); 281 | } 282 | 283 | /* (non-Javadoc) 284 | * @see java.lang.Object#toString() 285 | */ 286 | @Override 287 | public String toString() { 288 | StringBuffer sb = new StringBuffer(); 289 | sb.append("{"); 290 | sb.append("m=" + m); 291 | sb.append(", "); 292 | sb.append("n=" + n); 293 | sb.append("}"); 294 | return sb.toString(); 295 | } 296 | } 297 | 298 | @Override 299 | public int getBytesAllocated() { 300 | return Double.SIZE << 3; 301 | } 302 | 303 | @Override 304 | public Double buldFromBytes(byte[] bytes) { 305 | if (bytes.length != getBytesAllocated()) { 306 | throw new IllegalArgumentException( 307 | "To build from byte array I need array of size: " 308 | + getBytesAllocated()); 309 | } 310 | return ByteBuffer.wrap(bytes).getDouble(); 311 | 312 | } 313 | 314 | @Override 315 | public byte[] getByteArray(Double value) { 316 | int byteAllocated = getBytesAllocated(); 317 | ByteBuffer buff = ByteBuffer.allocate(byteAllocated); 318 | buff.putDouble(value); 319 | return buff.array(); 320 | } 321 | 322 | @Override 323 | public Class getStorageClazz() { 324 | return Double.class; 325 | } 326 | 327 | @Override 328 | protected Double zero() { 329 | return Zeros.DOUBLE; 330 | } 331 | } 332 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLStructure.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | /** 9 | * This class represents Matlab's Structure object (structure array). 10 | * 11 | * Note: array of structures can contain only structures of the same type 12 | * , that means structures that have the same field names. 13 | * 14 | * @author Wojciech Gradkowski 15 | */ 16 | public class MLStructure extends MLStructureObjectBase { 17 | public MLStructure(String name, int[] dims) { 18 | this(name, dims, 0); 19 | } 20 | 21 | public MLStructure(String name, int[] dims, int attributes) { 22 | super(name, dims, MLArray.mxSTRUCT_CLASS, attributes); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLStructureObjectBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.io.ByteArrayOutputStream; 9 | import java.io.DataOutputStream; 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | import java.util.Arrays; 13 | import java.util.Collection; 14 | import java.util.HashMap; 15 | import java.util.LinkedHashSet; 16 | import java.util.Map; 17 | import java.util.Set; 18 | import java.util.SortedMap; 19 | import java.util.TreeMap; 20 | 21 | import com.jmatio.common.DeterministicKeyMap; 22 | 23 | /** 24 | * Base class for MLStructure and MLObject. 25 | * 26 | * Note: array of structures can contain only structures of the same type 27 | * , that means structures must have the same field names. 28 | */ 29 | public abstract class MLStructureObjectBase extends MLArray { 30 | /** A Set that keeps structure field names */ 31 | protected Set keys = new LinkedHashSet(); 32 | /** Array of structures */ 33 | protected SortedMap> mlStructArray = new TreeMap>(); 34 | /** Current structure pointer for bulk insert */ 35 | protected int currentIndex = 0; 36 | 37 | protected MLStructureObjectBase(String name, int[] dims, int type, int attributes) { 38 | super(name, dims, type, attributes); 39 | } 40 | 41 | /** 42 | * Sets field for current structure 43 | * 44 | * @param name - name of the field 45 | * @param value - MLArray field value 46 | */ 47 | public void setField(String name, MLArray value) { 48 | setField(name, value, currentIndex); 49 | } 50 | 51 | /** 52 | * Sets field for (m,n)'th structure in struct array 53 | * 54 | * @param name - name of the field 55 | * @param value - MLArray field value 56 | * @param m 57 | * @param n 58 | */ 59 | public void setField(String name, MLArray value, int m, int n) { 60 | setField(name, value, getIndex(m, n)); 61 | } 62 | 63 | /** 64 | * Sets filed for structure described by index in struct array 65 | * 66 | * @param name - name of the field 67 | * @param value - MLArray field value 68 | * @param index 69 | */ 70 | public void setField(String name, MLArray value, int index) { 71 | keys.add(name); 72 | currentIndex = index; 73 | 74 | DeterministicKeyMap map = mlStructArray.get(index); 75 | if (map == null) { 76 | map = new DeterministicKeyMap(keys, new HashMap(keys.size())); 77 | mlStructArray.put(index, map); 78 | } 79 | map.put(name, value); 80 | } 81 | 82 | /** 83 | * Gets the maximum length of field descriptor 84 | * 85 | * @return 86 | */ 87 | public int getMaxFieldLenth() { 88 | //get max field name 89 | int maxLen = 0; 90 | for (String s : keys) { 91 | maxLen = Math.max(maxLen, s.length()); 92 | } 93 | return maxLen + 1; 94 | } 95 | 96 | /** 97 | * Dumps field names to byte array. Field names are written as Zero End Strings 98 | * 99 | * @return 100 | */ 101 | public byte[] getKeySetToByteArray() { 102 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 103 | DataOutputStream dos = new DataOutputStream(baos); 104 | 105 | char[] buffer = new char[getMaxFieldLenth()]; 106 | 107 | try { 108 | for (String s : keys) { 109 | Arrays.fill(buffer, (char) 0); 110 | System.arraycopy(s.toCharArray(), 0, buffer, 0, s.length()); 111 | dos.writeBytes(new String(buffer)); 112 | } 113 | } catch (IOException e) { 114 | System.err.println("Could not write Structure key set to byte array: " + e); 115 | return new byte[0]; 116 | } 117 | return baos.toByteArray(); 118 | 119 | } 120 | 121 | /** 122 | * Gets all field from sruct array as flat list of fields. 123 | * 124 | * @return 125 | */ 126 | public Collection getAllFields() { 127 | ArrayList fields = new ArrayList(); 128 | 129 | for (Map struct : mlStructArray.values()) { 130 | fields.addAll(struct.values()); 131 | } 132 | return fields; 133 | } 134 | 135 | /** 136 | * Returns the {@link Collection} of keys for this structure. 137 | * @return the {@link Collection} of keys for this structure 138 | */ 139 | public Collection getFieldNames() { 140 | return new LinkedHashSet(keys); 141 | } 142 | 143 | /** 144 | * Gets a value of the field described by name from current struct 145 | * in struct array or null if the field doesn't exist. 146 | * 147 | * @param name 148 | * @return 149 | */ 150 | public MLArray getField(String name) { 151 | return getField(name, currentIndex); 152 | } 153 | 154 | /** Returns all the fields for the given index. */ 155 | public Map getFields(int i) { 156 | return mlStructArray.get(i); 157 | } 158 | 159 | /** 160 | * Gets a value of the field described by name from (m,n)'th struct 161 | * in struct array or null if the field doesn't exist. 162 | * 163 | * @param name 164 | * @param m 165 | * @param n 166 | * @return 167 | */ 168 | public MLArray getField(String name, int m, int n) { 169 | return getField(name, getIndex(m, n)); 170 | } 171 | 172 | /** 173 | * Gets a value of the field described by name from index'th struct 174 | * in struct array or null if the field doesn't exist. 175 | * 176 | * @param name 177 | * @param index 178 | * @return value of the field or null if the field doesn't exist 179 | */ 180 | public MLArray getField(String name, int index) { 181 | if (mlStructArray.isEmpty()) { 182 | return null; 183 | } 184 | return mlStructArray.get(index).get(name); 185 | } 186 | 187 | /* (non-Javadoc) 188 | * @see com.paradigmdesigner.matlab.types.MLArray#contentToString() 189 | */ 190 | public String contentToString() { 191 | StringBuffer sb = new StringBuffer(); 192 | sb.append(name + " = \n"); 193 | 194 | if (getM() * getN() == 1) { 195 | for (String key : keys) { 196 | sb.append("\t" + key + " : " + getField(key) + "\n"); 197 | } 198 | } else { 199 | sb.append("\n"); 200 | sb.append(getM() + "x" + getN()); 201 | sb.append(" struct array with fields: \n"); 202 | for (String key : keys) { 203 | sb.append("\t" + key + "\n"); 204 | } 205 | } 206 | return sb.toString(); 207 | } 208 | 209 | } 210 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLUInt16.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | public class MLUInt16 extends MLInt16 { 9 | 10 | public MLUInt16(String name, int[] dims, int type, int attributes) { 11 | super(name, dims, type, attributes); 12 | } 13 | 14 | public MLUInt16(String name, Short[] vals, int m) { 15 | super(name, vals, m); 16 | } 17 | 18 | public MLUInt16(String name, int[] dims) { 19 | super(name, dims); 20 | } 21 | 22 | public MLUInt16(String name, short[][] vals) { 23 | super(name, vals); 24 | } 25 | 26 | public MLUInt16(String name, short[] vals, int m) { 27 | super(name, vals, m); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLUInt32.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | public class MLUInt32 extends MLInt32 { 9 | 10 | public MLUInt32(String name, int[] dims, int type, int attributes) { 11 | super(name, dims, type, attributes); 12 | } 13 | 14 | public MLUInt32(String name, int[] vals, int m) { 15 | super(name, vals, m); 16 | } 17 | 18 | public MLUInt32(String name, int[] dims) { 19 | super(name, dims); 20 | } 21 | 22 | public MLUInt32(String name, int[][] vals) { 23 | super(name, vals); 24 | } 25 | 26 | public MLUInt32(String name, Integer[] vals, int m) { 27 | super(name, vals, m); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLUInt64.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.nio.ByteBuffer; 9 | 10 | /** 11 | * Class represents Int64 (long) array (matrix) 12 | * 13 | * @author Wojciech Gradkowski 14 | */ 15 | public class MLUInt64 extends MLNumericArray { 16 | 17 | /** 18 | * Normally this constructor is used only by MatFileReader and MatFileWriter 19 | * 20 | * @param name - array name 21 | * @param dims - array dimensions 22 | * @param type - array type: here mxDOUBLE_CLASS 23 | * @param attributes - array flags 24 | */ 25 | public MLUInt64(String name, int[] dims, int type, int attributes) { 26 | super(name, dims, type, attributes); 27 | } 28 | 29 | /** 30 | * Create a {@link MLUInt64} array with given name, 31 | * and dimensions. 32 | * 33 | * @param name - array name 34 | * @param dims - array dimensions 35 | */ 36 | public MLUInt64(String name, int[] dims) { 37 | super(name, dims, MLArray.mxUINT64_CLASS, 0); 38 | } 39 | 40 | /** 41 | * Jama [math.nist.gov] style: 42 | * construct a 2D real matrix from a one-dimensional packed array 43 | * 44 | * @param name - array name 45 | * @param vals - One-dimensional array of doubles, packed by columns (ala Fortran). 46 | * @param m - Number of rows 47 | */ 48 | public MLUInt64(String name, Long[] vals, int m) { 49 | super(name, MLArray.mxUINT64_CLASS, vals, m); 50 | } 51 | 52 | /** 53 | * Jama [math.nist.gov] style: 54 | * construct a 2D real matrix from byte[][] 55 | * 56 | * Note: array is converted to Byte[] 57 | * 58 | * @param name - array name 59 | * @param vals - two-dimensional array of values 60 | */ 61 | public MLUInt64(String name, long[][] vals) { 62 | this(name, long2DToLong(vals), vals.length); 63 | } 64 | 65 | /** 66 | * Jama [math.nist.gov] style: 67 | * construct a matrix from a one-dimensional packed array 68 | * 69 | * @param name - array name 70 | * @param vals - One-dimensional array of doubles, packed by columns (ala Fortran). 71 | * @param m - Number of rows 72 | */ 73 | public MLUInt64(String name, long[] vals, int m) { 74 | this(name, castToLong(vals), m); 75 | } 76 | 77 | /* (non-Javadoc) 78 | * @see ca.mjdsystems.jmatio.types.GenericArrayCreator#createArray(int, int) 79 | */ 80 | public Long[] createArray(int m, int n) { 81 | return new Long[m * n]; 82 | } 83 | 84 | /** 85 | * Gets two-dimensional real array. 86 | * 87 | * @return - 2D real array 88 | */ 89 | public long[][] getArray() { 90 | long[][] result = new long[getM()][]; 91 | 92 | for (int m = 0; m < getM(); m++) { 93 | result[m] = new long[getN()]; 94 | 95 | for (int n = 0; n < getN(); n++) { 96 | result[m][n] = getReal(m, n); 97 | } 98 | } 99 | return result; 100 | } 101 | 102 | /** 103 | * Casts Double[] to byte[] 104 | * 105 | * @param - source Long[] 106 | * @return - result long[] 107 | */ 108 | private static Long[] castToLong(long[] d) { 109 | Long[] dest = new Long[d.length]; 110 | for (int i = 0; i < d.length; i++) { 111 | dest[i] = (long) d[i]; 112 | } 113 | return dest; 114 | } 115 | 116 | /** 117 | * Converts byte[][] to Long[] 118 | * 119 | * @param dd 120 | * @return 121 | */ 122 | private static Long[] long2DToLong(long[][] dd) { 123 | Long[] d = new Long[dd.length * dd[0].length]; 124 | for (int n = 0; n < dd[0].length; n++) { 125 | for (int m = 0; m < dd.length; m++) { 126 | d[m + n * dd.length] = dd[m][n]; 127 | } 128 | } 129 | return d; 130 | } 131 | 132 | public Long buldFromBytes(byte[] bytes) { 133 | if (bytes.length != getBytesAllocated()) { 134 | throw new IllegalArgumentException( 135 | "To build from byte array I need array of size: " 136 | + getBytesAllocated()); 137 | } 138 | return ByteBuffer.wrap(bytes).getLong(); 139 | } 140 | 141 | public int getBytesAllocated() { 142 | return Long.SIZE >> 3; 143 | } 144 | 145 | public Class getStorageClazz() { 146 | return Long.class; 147 | } 148 | 149 | public byte[] getByteArray(Long value) { 150 | int byteAllocated = getBytesAllocated(); 151 | ByteBuffer buff = ByteBuffer.allocate(byteAllocated); 152 | buff.putLong(value); 153 | return buff.array(); 154 | } 155 | 156 | @Override 157 | protected Long zero() { 158 | return Zeros.LONG; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/MLUInt8.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import java.nio.ByteBuffer; 9 | 10 | /** 11 | * Class represents UInt8 (byte) array (matrix) 12 | * 13 | * @author Wojciech Gradkowski 14 | */ 15 | public class MLUInt8 extends MLNumericArray { 16 | 17 | /** 18 | * Normally this constructor is used only by MatFileReader and MatFileWriter 19 | * 20 | * @param name - array name 21 | * @param dims - array dimensions 22 | * @param type - array type: here mxDOUBLE_CLASS 23 | * @param attributes - array flags 24 | */ 25 | public MLUInt8(String name, int[] dims, int type, int attributes) { 26 | super(name, dims, type, attributes); 27 | } 28 | 29 | /** 30 | * Create a {@link MLUInt8} array with given name, 31 | * and dimensions. 32 | * 33 | * @param name - array name 34 | * @param dims - array dimensions 35 | */ 36 | public MLUInt8(String name, int[] dims) { 37 | super(name, dims, MLArray.mxUINT8_CLASS, 0); 38 | } 39 | 40 | /** 41 | * Jama [math.nist.gov] style: 42 | * construct a 2D real matrix from a one-dimensional packed array 43 | * 44 | * @param name - array name 45 | * @param vals - One-dimensional array of doubles, packed by columns (ala Fortran). 46 | * @param m - Number of rows 47 | */ 48 | public MLUInt8(String name, Byte[] vals, int m) { 49 | super(name, MLArray.mxUINT8_CLASS, vals, m); 50 | } 51 | 52 | /** 53 | * Jama [math.nist.gov] style: 54 | * construct a 2D real matrix from byte[][] 55 | * 56 | * Note: array is converted to Byte[] 57 | * 58 | * @param name - array name 59 | * @param vals - two-dimensional array of values 60 | */ 61 | public MLUInt8(String name, byte[][] vals) { 62 | this(name, byte2DToByte(vals), vals.length); 63 | } 64 | 65 | /** 66 | * Jama [math.nist.gov] style: 67 | * construct a matrix from a one-dimensional packed array 68 | * 69 | * @param name - array name 70 | * @param vals - One-dimensional array of doubles, packed by columns (ala Fortran). 71 | * @param m - Number of rows 72 | */ 73 | public MLUInt8(String name, byte[] vals, int m) { 74 | this(name, castToByte(vals), m); 75 | } 76 | 77 | /* (non-Javadoc) 78 | * @see com.jmatio.types.GenericArrayCreator#createArray(int, int) 79 | */ 80 | public Byte[] createArray(int m, int n) { 81 | return new Byte[m * n]; 82 | } 83 | 84 | /** 85 | * Gets two-dimensional real array. 86 | * 87 | * @return - 2D real array 88 | */ 89 | public byte[][] getArray() { 90 | byte[][] result = new byte[getM()][]; 91 | 92 | for (int m = 0; m < getM(); m++) { 93 | result[m] = new byte[getN()]; 94 | 95 | for (int n = 0; n < getN(); n++) { 96 | result[m][n] = get(m, n); 97 | } 98 | } 99 | return result; 100 | } 101 | 102 | /** 103 | * Casts Double[] to byte[] 104 | * 105 | * @param - source Byte[] 106 | * @return - result byte[] 107 | */ 108 | private static Byte[] castToByte(byte[] d) { 109 | Byte[] dest = new Byte[d.length]; 110 | for (int i = 0; i < d.length; i++) { 111 | dest[i] = (byte) d[i]; 112 | } 113 | return dest; 114 | } 115 | 116 | /** 117 | * Converts byte[][] to Byte[] 118 | * 119 | * @param dd 120 | * @return 121 | */ 122 | private static Byte[] byte2DToByte(byte[][] dd) { 123 | Byte[] d = new Byte[dd.length * dd[0].length]; 124 | for (int n = 0; n < dd[0].length; n++) { 125 | for (int m = 0; m < dd.length; m++) { 126 | d[m + n * dd.length] = dd[m][n]; 127 | } 128 | } 129 | return d; 130 | } 131 | 132 | public Byte buldFromBytes(byte[] bytes) { 133 | if (bytes.length != getBytesAllocated()) { 134 | throw new IllegalArgumentException( 135 | "To build from byte array I need array of size: " 136 | + getBytesAllocated()); 137 | } 138 | return bytes[0]; 139 | } 140 | 141 | public byte[] getByteArray(Byte value) { 142 | return new byte[]{value}; 143 | } 144 | 145 | public int getBytesAllocated() { 146 | return Byte.SIZE >> 3; 147 | } 148 | 149 | public Class getStorageClazz() { 150 | return Byte.class; 151 | } 152 | 153 | /** 154 | * Override to accelerate the performance 155 | * 156 | * @see com.jmatio.types.MLNumericArray#get(java.nio.ByteBuffer, int) 157 | */ 158 | @Override 159 | protected Byte _get(ByteBuffer buffer, int index) { 160 | return buffer.get(index); 161 | } 162 | 163 | @Override 164 | protected Byte zero() { 165 | return Zeros.BYTE; 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/main/java/com/jmatio/types/Zeros.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | /** Singleton implementations of zero for each number type. */ 9 | public class Zeros { 10 | static final Double DOUBLE = Double.valueOf(0.0); 11 | static final Float FLOAT = Float.valueOf(0.0f); 12 | 13 | static final Long LONG = Long.valueOf(0l); 14 | static final Integer INTEGER = Integer.valueOf(0); 15 | static final Short SHORT = Short.valueOf((short) 0); 16 | static final Byte BYTE = Byte.valueOf((byte) 0); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/main.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/test/java/com/jmatio/common/util/DeterministicKeyMapTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.common.util; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.LinkedHashMap; 11 | import java.util.LinkedHashSet; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.Set; 15 | 16 | import org.junit.Assert; 17 | import org.junit.Test; 18 | 19 | import com.jmatio.common.DeterministicKeyMap; 20 | 21 | public class DeterministicKeyMapTest { 22 | @Test 23 | public void testOrdering() { 24 | Set ordering = new LinkedHashSet(); 25 | DeterministicKeyMap map = new DeterministicKeyMap(ordering, new LinkedHashMap()); 26 | Assert.assertEquals(true, map.keySet().isEmpty()); 27 | Assert.assertEquals(true, map.values().isEmpty()); 28 | Assert.assertEquals(true, map.entrySet().isEmpty()); 29 | 30 | // add them to the map in one order 31 | map.put(1, "1"); 32 | map.put(2, "2"); 33 | map.put(3, "3"); 34 | 35 | { 36 | // and pull them out in another 37 | ordering.add(3); 38 | ordering.add(2); 39 | ordering.add(1); 40 | 41 | List keys = new ArrayList(map.keySet()); 42 | List values = new ArrayList(map.values()); 43 | Assert.assertEquals(Arrays.asList(3, 2, 1), keys); 44 | Assert.assertEquals(Arrays.asList("3", "2", "1"), values); 45 | List> entries = new ArrayList>(map.entrySet()); 46 | Assert.assertEquals(keys.size(), entries.size()); 47 | for (int i = 0; i < keys.size(); ++i) { 48 | Assert.assertEquals(keys.get(i), entries.get(i).getKey()); 49 | Assert.assertEquals(values.get(i), entries.get(i).getValue()); 50 | } 51 | } 52 | 53 | { 54 | // now pull them out in a different order 55 | ordering.clear(); 56 | ordering.add(2); 57 | ordering.add(3); 58 | ordering.add(1); 59 | 60 | List keys = new ArrayList(map.keySet()); 61 | List values = new ArrayList(map.values()); 62 | Assert.assertEquals(Arrays.asList(2, 3, 1), keys); 63 | Assert.assertEquals(Arrays.asList("2", "3", "1"), values); 64 | List> entries = new ArrayList>(map.entrySet()); 65 | Assert.assertEquals(keys.size(), entries.size()); 66 | for (int i = 0; i < keys.size(); ++i) { 67 | Assert.assertEquals(keys.get(i), entries.get(i).getKey()); 68 | Assert.assertEquals(values.get(i), entries.get(i).getValue()); 69 | } 70 | } 71 | 72 | { 73 | // now remove an object from the map 74 | map.remove(3); 75 | 76 | List keys = new ArrayList(map.keySet()); 77 | List values = new ArrayList(map.values()); 78 | Assert.assertEquals(Arrays.asList(2, 1), keys); 79 | Assert.assertEquals(Arrays.asList("2", "1"), values); 80 | List> entries = new ArrayList>(map.entrySet()); 81 | Assert.assertEquals(keys.size(), entries.size()); 82 | for (int i = 0; i < keys.size(); ++i) { 83 | Assert.assertEquals(keys.get(i), entries.get(i).getKey()); 84 | Assert.assertEquals(values.get(i), entries.get(i).getValue()); 85 | } 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/test/java/com/jmatio/common/util/MLArrayQueryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.common.util; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | 10 | import java.io.File; 11 | import java.io.IOException; 12 | import java.util.Map; 13 | 14 | import org.junit.Before; 15 | import org.junit.Ignore; 16 | import org.junit.Test; 17 | 18 | import com.jmatio.io.MatFileReader; 19 | import com.jmatio.types.MLArray; 20 | import com.jmatio.types.MLChar; 21 | import com.jmatio.types.MLStructure; 22 | 23 | public class MLArrayQueryTest { 24 | private File spmFile = new File("src/test/resources/SPM.mat"); 25 | private MLArray array; 26 | 27 | @Before 28 | public void setUp() throws IOException { 29 | MatFileReader reader = new MatFileReader(); 30 | Map content = reader.read(spmFile); 31 | array = content.get("SPM"); 32 | } 33 | 34 | @Test 35 | public void testStruct() { 36 | MLStructure actual = (MLStructure) MLArrayQuery.q(array, "SPM"); 37 | assertEquals("SPM", actual.getName()); 38 | assertEquals(1, actual.getSize()); 39 | } 40 | 41 | @Test 42 | public void testStruct2() { 43 | MLStructure actual = (MLStructure) MLArrayQuery.q(array, "SPM(1,1)"); 44 | assertEquals("SPM", actual.getName()); 45 | assertEquals(1, actual.getSize()); 46 | } 47 | 48 | @Test 49 | public void testStruct3() { 50 | MLStructure actual = (MLStructure) MLArrayQuery.q(array, "SPM(1)"); 51 | assertEquals("SPM", actual.getName()); 52 | assertEquals(1, actual.getSize()); 53 | } 54 | 55 | @Test 56 | public void testCharArray1() { 57 | String actual = (String) MLArrayQuery.q(array, "SPM.xCon(1,2).name(1)"); 58 | assertEquals("bike", actual); 59 | } 60 | 61 | @Test 62 | public void testCharArray2() { 63 | MLChar actual = (MLChar) MLArrayQuery.q(array, "SPM.xCon(1,2).name"); 64 | assertEquals("bike", actual.getString(0)); 65 | } 66 | 67 | @Test 68 | public void testCharArray3() { 69 | char actual = (Character) MLArrayQuery.q(array, "SPM.xCon(1,2).name(1,2)"); 70 | assertEquals('i', actual); 71 | } 72 | 73 | @Test 74 | public void testCell() { 75 | MLChar actual = (MLChar) MLArrayQuery.q(array, "SPM.Sess(1,1).U(1,1).name"); 76 | assertEquals("aquarium", actual.getString(0)); 77 | 78 | String str = (String) MLArrayQuery.q(array, "SPM.Sess(1,1).U(1,2).name(1)"); 79 | assertEquals("bike", str); 80 | } 81 | 82 | @Ignore 83 | @Test 84 | public void test() throws IOException { 85 | System.out.println(MLArrayQuery.q(array, "SPM.xCon(1,2).c")); 86 | System.out.println(MLArrayQuery.q(array, "SPM.xCon(1,2).c(2,1)")); 87 | System.out.println(MLArrayQuery.q(array, "SPM.xCon(1,2).name(1)")); 88 | System.out.println(MLArrayQuery.q(array, "SPM.Sess(1,1).U(1,1).name")); 89 | System.out.println(MLArrayQuery.q(array, "SPM.xY.RT(1)")); 90 | System.out.println(MLArrayQuery.q((MLArray) MLArrayQuery.q(array, "SPM.xCon(1,2).c"), ("c(1,1)"))); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/test/java/com/jmatio/io/MatlabMCOSTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io; 7 | 8 | import static org.hamcrest.CoreMatchers.equalTo; 9 | import static org.hamcrest.CoreMatchers.notNullValue; 10 | import static org.junit.Assert.assertThat; 11 | 12 | import java.io.BufferedOutputStream; 13 | import java.io.File; 14 | import java.io.FileOutputStream; 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | import java.io.OutputStream; 18 | import java.util.Map; 19 | 20 | import org.junit.Rule; 21 | import org.junit.Test; 22 | import org.junit.rules.TemporaryFolder; 23 | import org.junit.runner.RunWith; 24 | import org.junit.runners.JUnit4; 25 | 26 | import com.jmatio.types.MLArray; 27 | import com.jmatio.types.MLChar; 28 | import com.jmatio.types.MLDouble; 29 | import com.jmatio.types.MLInt8; 30 | import com.jmatio.types.MLObject; 31 | 32 | /** 33 | * This test verifies that ReducedHeader generated mat files work correctly. 34 | * 35 | * @author Matthew Dawson 36 | */ 37 | @RunWith(JUnit4.class) 38 | public class MatlabMCOSTest { 39 | @Rule 40 | public TemporaryFolder folder = new TemporaryFolder(); 41 | 42 | @Test 43 | public void testParsingSimpleEmptyMCOS() throws IOException { 44 | File file = fileFromStream("/mcos/simpleempty.mat"); 45 | MatFileReader reader = new MatFileReader(file); 46 | Map content = reader.getContent(); 47 | 48 | assertThat(content.size(), equalTo(1)); 49 | 50 | MLObject obj = (MLObject) content.get("obj"); 51 | assertThat(obj, notNullValue()); 52 | 53 | assertThat(obj.getName(), equalTo("obj")); 54 | assertThat(obj.getClassName(), equalTo("SimpleEmpty")); 55 | assertThat(obj.getFieldNames().size(), equalTo(0)); 56 | } 57 | 58 | @Test 59 | public void testParsingMultipleSimpleEmptyMCOS() throws IOException { 60 | File file = fileFromStream("/mcos/simpleempty_multiple.mat"); 61 | MatFileReader reader = new MatFileReader(file); 62 | Map content = reader.getContent(); 63 | 64 | assertThat(content.size(), equalTo(2)); 65 | 66 | MLObject obj = (MLObject) content.get("obj1"); 67 | assertThat(obj, notNullValue()); 68 | 69 | assertThat(obj.getName(), equalTo("obj1")); 70 | assertThat(obj.getClassName(), equalTo("SimpleEmpty")); 71 | assertThat(obj.getFieldNames().size(), equalTo(0)); 72 | 73 | obj = (MLObject) content.get("obj2"); 74 | assertThat(obj, notNullValue()); 75 | 76 | assertThat(obj.getName(), equalTo("obj2")); 77 | assertThat(obj.getClassName(), equalTo("SimpleEmpty")); 78 | assertThat(obj.getFieldNames().size(), equalTo(0)); 79 | } 80 | 81 | @Test 82 | public void testParsingSimpleSingleTextUnmodifiedMCOS() throws IOException { 83 | File file = fileFromStream("/mcos/simplesingletext_unmodified.mat"); 84 | MatFileReader reader = new MatFileReader(file); 85 | Map content = reader.getContent(); 86 | 87 | assertThat(content.size(), equalTo(1)); 88 | 89 | MLObject obj = (MLObject) content.get("obj"); 90 | assertThat(obj, notNullValue()); 91 | 92 | assertThat(obj.getName(), equalTo("obj")); 93 | assertThat(obj.getClassName(), equalTo("SimpleSingleText")); 94 | Map fields = obj.getFields(0); 95 | assertThat(fields.size(), equalTo(1)); 96 | 97 | MLChar field = (MLChar) fields.get("test_text"); 98 | assertThat(field.getString(0), equalTo("Default text")); 99 | } 100 | 101 | @Test 102 | public void testParsingSimpleSingleTextMultipleMCOS() throws IOException { 103 | File file = fileFromStream("/mcos/simplesingletext_multiple.mat"); 104 | MatFileReader reader = new MatFileReader(file); 105 | Map content = reader.getContent(); 106 | 107 | assertThat(content.size(), equalTo(3)); 108 | 109 | MLObject obj = (MLObject) content.get("obj1"); 110 | assertThat(obj, notNullValue()); 111 | 112 | assertThat(obj.getName(), equalTo("obj1")); 113 | assertThat(obj.getClassName(), equalTo("SimpleSingleText")); 114 | Map fields = obj.getFields(0); 115 | assertThat(fields.size(), equalTo(1)); 116 | 117 | MLChar field = (MLChar) fields.get("test_text"); 118 | assertThat(field.getString(0), equalTo("other text 1")); 119 | 120 | obj = (MLObject) content.get("obj2"); 121 | assertThat(obj, notNullValue()); 122 | 123 | assertThat(obj.getName(), equalTo("obj2")); 124 | assertThat(obj.getClassName(), equalTo("SimpleSingleText")); 125 | fields = obj.getFields(0); 126 | assertThat(fields.size(), equalTo(1)); 127 | 128 | field = (MLChar) fields.get("test_text"); 129 | assertThat(field.getString(0), equalTo("Default text")); 130 | 131 | obj = (MLObject) content.get("obj3"); 132 | assertThat(obj, notNullValue()); 133 | 134 | assertThat(obj.getName(), equalTo("obj3")); 135 | assertThat(obj.getClassName(), equalTo("SimpleSingleText")); 136 | fields = obj.getFields(0); 137 | assertThat(fields.size(), equalTo(1)); 138 | 139 | field = (MLChar) fields.get("test_text"); 140 | assertThat(field.getString(0), equalTo("other text 3")); 141 | } 142 | 143 | @Test 144 | public void testParsingHandleSinglePropertyMultipleMCOS() throws IOException { 145 | File file = fileFromStream("/mcos/handlesingle_multiple.mat"); 146 | MatFileReader reader = new MatFileReader(file); 147 | Map content = reader.getContent(); 148 | 149 | assertThat(content.size(), equalTo(4)); 150 | 151 | MLObject obj = (MLObject) content.get("obj1"); 152 | assertThat(obj, notNullValue()); 153 | 154 | assertThat(obj.getName(), equalTo("obj1")); 155 | assertThat(obj.getClassName(), equalTo("HandleSingle")); 156 | assertThat(((MLObject) content.get("obj3")).getFields(0), equalTo(obj.getFields(0))); 157 | Map fields = obj.getFields(0); 158 | assertThat(fields.size(), equalTo(1)); 159 | 160 | MLInt8 intField = (MLInt8) fields.get("myelement"); 161 | assertThat(intField.getSize(), equalTo(1)); 162 | assertThat(intField.get(0).byteValue(), equalTo((byte) 25)); 163 | 164 | obj = (MLObject) content.get("obj3"); 165 | assertThat(obj, notNullValue()); 166 | 167 | assertThat(obj.getName(), equalTo("obj3")); 168 | assertThat(obj.getClassName(), equalTo("HandleSingle")); 169 | assertThat(((MLObject) content.get("obj1")).getFields(0), equalTo(obj.getFields(0))); 170 | fields = obj.getFields(0); 171 | assertThat(fields.size(), equalTo(1)); 172 | 173 | intField = (MLInt8) fields.get("myelement"); 174 | assertThat(intField.getSize(), equalTo(1)); 175 | assertThat(intField.get(0).byteValue(), equalTo((byte) 25)); 176 | 177 | obj = (MLObject) content.get("obj2"); 178 | assertThat(obj, notNullValue()); 179 | 180 | assertThat(obj.getName(), equalTo("obj2")); 181 | assertThat(obj.getClassName(), equalTo("HandleSingle")); 182 | assertThat(((MLObject) content.get("obj4")).getFields(0), equalTo(obj.getFields(0))); 183 | fields = obj.getFields(0); 184 | assertThat(fields.size(), equalTo(1)); 185 | 186 | MLChar charField = (MLChar) fields.get("myelement"); 187 | assertThat(charField.getString(0), equalTo("testing")); 188 | 189 | obj = (MLObject) content.get("obj4"); 190 | assertThat(obj, notNullValue()); 191 | 192 | assertThat(obj.getName(), equalTo("obj4")); 193 | assertThat(obj.getClassName(), equalTo("HandleSingle")); 194 | assertThat(((MLObject) content.get("obj2")).getFields(0), equalTo(obj.getFields(0))); 195 | fields = obj.getFields(0); 196 | assertThat(fields.size(), equalTo(1)); 197 | 198 | charField = (MLChar) fields.get("myelement"); 199 | assertThat(charField.getString(0), equalTo("testing")); 200 | } 201 | 202 | @Test 203 | public void testMultipleMCOSInArray() throws IOException { 204 | File file = fileFromStream("/mcos/simplesingletext_multiplearray.mat"); 205 | MatFileReader reader = new MatFileReader(file); 206 | Map content = reader.getContent(); 207 | 208 | assertThat(content.size(), equalTo(1)); 209 | 210 | MLObject obj = (MLObject) content.get("a"); 211 | assertThat(obj, notNullValue()); 212 | 213 | assertThat(obj.getName(), equalTo("a")); 214 | assertThat(obj.getClassName(), equalTo("SimpleSingleText")); 215 | assertThat(((MLDouble) obj.getFields(0).get("test_text")).get(0), equalTo(1.0)); 216 | assertThat(((MLDouble) obj.getFields(1).get("test_text")).get(0), equalTo(2.0)); 217 | assertThat(((MLDouble) obj.getFields(2).get("test_text")).get(0), equalTo(3.0)); 218 | assertThat(((MLDouble) obj.getFields(3).get("test_text")).get(0), equalTo(4.0)); 219 | } 220 | 221 | private File fileFromStream(String location) throws IOException { 222 | String outname = location.replace("/", "_"); 223 | File f = folder.newFile(outname); 224 | InputStream stream = MatlabMCOSTest.class.getResourceAsStream(location); 225 | OutputStream fos = new BufferedOutputStream(new FileOutputStream(f)); 226 | byte[] buffer = new byte[1024]; 227 | int read = 0; 228 | while ((read = stream.read(buffer)) != -1) { 229 | fos.write(buffer, 0, read); 230 | } 231 | fos.flush(); 232 | fos.close(); 233 | return f; 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /src/test/java/com/jmatio/io/StructureWithTimeseriesTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.io; 7 | 8 | import static org.hamcrest.CoreMatchers.*; 9 | import static org.junit.Assert.*; 10 | 11 | import java.util.Map; 12 | 13 | import org.hamcrest.CoreMatchers; 14 | import org.hamcrest.CustomMatcher; 15 | import org.hamcrest.Matcher; 16 | import org.junit.Test; 17 | import org.junit.runner.RunWith; 18 | import org.junit.runners.JUnit4; 19 | 20 | import com.jmatio.types.MLArray; 21 | import com.jmatio.types.MLChar; 22 | import com.jmatio.types.MLDouble; 23 | import com.jmatio.types.MLInt8; 24 | import com.jmatio.types.MLObject; 25 | import com.jmatio.types.MLStructure; 26 | import com.jmatio.types.MLStructureObjectBase; 27 | 28 | /** 29 | * This test verifies {@link issue #13}. 30 | *

31 | * During tests the introspection of data did not show essential vectors. 32 | * It comes out that the properties are propagated, but their corresponding 33 | * names are not propagated to {@link MLStructureObjectBase#getFieldNames()}. 34 | * 35 | * @author Piotr Smolinski 36 | */ 37 | @RunWith(JUnit4.class) 38 | public class StructureWithTimeseriesTest { 39 | 40 | /** 41 | * Tests reading of a timeseries object contained in a struct. 42 | */ 43 | @Test 44 | public void testReadingTimeSeries() throws Exception { 45 | 46 | MatFileReader reader = new MatFileReader( 47 | getClass().getResourceAsStream("/timeseries.mat"), 48 | MatFileType.Regular); 49 | 50 | Map content = reader.getContent(); 51 | 52 | assertThat(content.get("s"), is(instanceOf(MLStructure.class))); 53 | MLStructure s = (MLStructure) content.get("s"); 54 | 55 | assertThat(s.getField("test"), is(instanceOf(MLObject.class))); 56 | MLObject test = (MLObject) s.getField("test"); 57 | assertThat(test.getClassName(), equalTo("timeseries")); 58 | 59 | assertThat(test.getField("Data_"), is(instanceOf(MLDouble.class))); 60 | MLDouble data = (MLDouble) test.getField("Data_"); 61 | assertThat(data.getSize(), equalTo(5)); 62 | 63 | assertThat(test.getField("Quality_"), is(instanceOf(MLInt8.class))); 64 | MLInt8 quality = (MLInt8) test.getField("Quality_"); 65 | assertThat(quality.getSize(), equalTo(5)); 66 | 67 | assertThat(test.getField("Time_"), isMatlabUndefined()); 68 | 69 | assertThat(test.getField("DataInfo"), not(isMatlabUndefined())); 70 | assertThat(test.getField("DataInfo"), is(instanceOf(MLObject.class))); 71 | MLObject dataInfo = (MLObject) test.getField("DataInfo"); 72 | assertThat(dataInfo.getClassName(), equalTo("datametadata")); 73 | 74 | assertThat(dataInfo.getField("Interpolation"), is(instanceOf(MLObject.class))); 75 | assertThat(dataInfo.getFieldNames(), hasItem("Interpolation")); 76 | 77 | assertThat(test.getField("QualityInfo"), not(isMatlabUndefined())); 78 | assertThat(test.getField("QualityInfo"), is(instanceOf(MLObject.class))); 79 | MLObject qualityInfo = (MLObject) test.getField("QualityInfo"); 80 | assertThat(qualityInfo.getClassName(), equalTo("qualmetadata")); 81 | 82 | assertThat(qualityInfo.getField("Version"), is(instanceOf(MLDouble.class))); 83 | assertThat(qualityInfo.getFieldNames(), hasItem("Version")); 84 | 85 | assertThat(test.getField("TimeInfo"), not(isMatlabUndefined())); 86 | assertThat(test.getField("TimeInfo"), is(instanceOf(MLObject.class))); 87 | MLObject timeInfo = (MLObject) test.getField("TimeInfo"); 88 | assertThat(timeInfo.getClassName(), equalTo("timemetadata")); 89 | 90 | // apparently this works even when #13 fix is not applied 91 | assertThat(timeInfo.getField("Time_"), is(instanceOf(MLDouble.class))); 92 | // but this fails 93 | assertThat(timeInfo.getFieldNames(), hasItem("Time_")); 94 | MLDouble timeInfoTime = (MLDouble) timeInfo.getField("Time_"); 95 | assertThat(timeInfoTime.getSize(), equalTo(5)); 96 | 97 | assertThat(timeInfo.getField("Units"), is(instanceOf(MLChar.class))); 98 | assertThat(timeInfo.getFieldNames(), hasItem("Units")); 99 | MLChar timeInfoUnits = (MLChar) timeInfo.getField("Units"); 100 | assertThat(timeInfoUnits.getString(0), equalTo("seconds")); 101 | 102 | } 103 | 104 | /** 105 | * Tests if given {@link MLArray} is undefined in sense of JMatIO. 106 | * Actually this should just return null, but in the JMatIO empty 107 | * properties are resolved to empty double vector 108 | */ 109 | private Matcher isMatlabUndefined() { 110 | return CoreMatchers.allOf( 111 | is(instanceOf(MLDouble.class)), 112 | new CustomMatcher("empty double vector") { 113 | @Override 114 | public boolean matches(Object item) { 115 | if (!(item instanceof MLDouble)) 116 | return false; 117 | return ((MLDouble) item).getSize() == 0; 118 | } 119 | }); 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/test/java/com/jmatio/types/MLNumericArrayTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code licensed under new-style BSD (see LICENSE). 3 | * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski 4 | * All code after tags/original: Copyright (c) 2015, DiffPlug 5 | */ 6 | package com.jmatio.types; 7 | 8 | import org.junit.Assert; 9 | import org.junit.Test; 10 | 11 | public class MLNumericArrayTest { 12 | @Test 13 | public void testMultipleDimArray() { 14 | int[] dims = new int[]{3, 4, 5}; 15 | MLInt32 multidim = new MLInt32("multiDimTest", dims); 16 | for (int i = 0; i < dims[0]; ++i) { 17 | for (int j = 0; j < dims[1]; ++j) { 18 | for (int k = 0; k < dims[2]; ++k) { 19 | int value = i * j * k; 20 | multidim.set(value, i, j, k); 21 | Assert.assertEquals(value, multidim.get(i, j, k).intValue()); 22 | } 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/matlab/com/jmatio/TestMultiDimArray.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | % determine if script is being run from maven style project directory 4 | % if so, set root dir approriately, otherwise just use current directory 5 | % in maven directory structure this file should be located in directory 6 | % project_root/src/test/matlab/com/jmatio/TestMultiDimArray.m 7 | proj_root = '../../../../../' 8 | test_rsrc_dir = 'src/test/resources/' 9 | 10 | rsrc_dir = strcat( proj_root, test_rsrc_dir ) 11 | 12 | fnMultiDimMatrix = 'multiDimMatrix.mat' 13 | 14 | % by default, use current directory as root 15 | test_dir = './'; 16 | if exist( rsrc_dir, 'dir' ) 17 | test_dir = rsrc_dir; 18 | end 19 | 20 | genMultiDimMatrix(strcat( test_dir, fnMultiDimMatrix )) 21 | 22 | 23 | 24 | 25 | function op = genMultiDimMatrix( filePath ) 26 | in = zeros(2, 3, 4, 5, 6); 27 | e = 0; 28 | for i =1:6 29 | for j = 1:5 30 | for k = 1:4 31 | for l = 1:3 32 | for m = 1:2 33 | in(m, l, k, j, i) = e; 34 | e = e + 1; 35 | end 36 | end 37 | end 38 | end 39 | end 40 | 41 | 42 | 43 | 44 | save( filePath, 'in' ) 45 | end 46 | -------------------------------------------------------------------------------- /src/test/matlab/com/jmatio/TestMultiDimComplexArray.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | % determine if script is being run from maven style project directory 4 | % if so, set root dir approriately, otherwise just use current directory 5 | % in maven directory structure this file should be located in directory 6 | % project_root/src/test/matlab/com/jmatio/TestMultiDimComplexArray.m 7 | proj_root = '../../../../../' 8 | test_rsrc_dir = 'src/test/resources/' 9 | 10 | rsrc_dir = strcat( proj_root, test_rsrc_dir ) 11 | 12 | fnMultiDimComplexMatrix = 'multiDimComplexMatrix.mat' 13 | 14 | % by default, use current directory as root 15 | test_dir = './'; 16 | if exist( rsrc_dir, 'dir' ) 17 | test_dir = rsrc_dir; 18 | end 19 | 20 | genMultiDimComplexMatrix(strcat( test_dir, fnMultiDimComplexMatrix )) 21 | 22 | 23 | 24 | 25 | function op = genMultiDimComplexMatrix( filePath ) 26 | a = zeros(2, 3, 4, 5, 6); 27 | in = complex(a, 0); 28 | e = 0; 29 | for i =1:6 30 | for j = 1:5 31 | for k = 1:4 32 | for l = 1:3 33 | for m = 1:2 34 | in(m, l, k, j, i) = complex(e, -e); 35 | e = e + 1; 36 | end 37 | end 38 | end 39 | end 40 | end 41 | 42 | 43 | 44 | 45 | save( filePath, 'in' ); 46 | end 47 | -------------------------------------------------------------------------------- /src/test/resources/SPM.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/SPM.mat -------------------------------------------------------------------------------- /src/test/resources/bigsparse.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/bigsparse.mat -------------------------------------------------------------------------------- /src/test/resources/cell.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/cell.mat -------------------------------------------------------------------------------- /src/test/resources/emptyname.mat: -------------------------------------------------------------------------------- 1 | MATLAB 5.0 MAT-file, Platform: GLNXA64, Created on: Thu May 1 14:36:03 2014 IM000 -------------------------------------------------------------------------------- /src/test/resources/handles.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/handles.mat -------------------------------------------------------------------------------- /src/test/resources/int32.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/int32.mat -------------------------------------------------------------------------------- /src/test/resources/int64.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/int64.mat -------------------------------------------------------------------------------- /src/test/resources/int8.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/int8.mat -------------------------------------------------------------------------------- /src/test/resources/java.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/java.mat -------------------------------------------------------------------------------- /src/test/resources/logical.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/logical.mat -------------------------------------------------------------------------------- /src/test/resources/matnativedouble.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/matnativedouble.mat -------------------------------------------------------------------------------- /src/test/resources/matnativedouble2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/matnativedouble2.mat -------------------------------------------------------------------------------- /src/test/resources/mcos/handlesingle_multiple.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/mcos/handlesingle_multiple.mat -------------------------------------------------------------------------------- /src/test/resources/mcos/simpleempty.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/mcos/simpleempty.mat -------------------------------------------------------------------------------- /src/test/resources/mcos/simpleempty_multiple.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/mcos/simpleempty_multiple.mat -------------------------------------------------------------------------------- /src/test/resources/mcos/simplesingletext_multiple.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/mcos/simplesingletext_multiple.mat -------------------------------------------------------------------------------- /src/test/resources/mcos/simplesingletext_multiplearray.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/mcos/simplesingletext_multiplearray.mat -------------------------------------------------------------------------------- /src/test/resources/mcos/simplesingletext_unmodified.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/mcos/simplesingletext_unmodified.mat -------------------------------------------------------------------------------- /src/test/resources/multiDimComplexMatrix.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/multiDimComplexMatrix.mat -------------------------------------------------------------------------------- /src/test/resources/multiDimMatrix.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/multiDimMatrix.mat -------------------------------------------------------------------------------- /src/test/resources/nan.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/nan.mat -------------------------------------------------------------------------------- /src/test/resources/object.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/object.mat -------------------------------------------------------------------------------- /src/test/resources/simplestruct.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/simplestruct.mat -------------------------------------------------------------------------------- /src/test/resources/simulink_tet_out.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/simulink_tet_out.mat -------------------------------------------------------------------------------- /src/test/resources/single.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/single.mat -------------------------------------------------------------------------------- /src/test/resources/sparse.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/sparse.mat -------------------------------------------------------------------------------- /src/test/resources/timeseries.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/timeseries.mat -------------------------------------------------------------------------------- /src/test/resources/uint32.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/uint32.mat -------------------------------------------------------------------------------- /src/test/resources/uint64.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/uint64.mat -------------------------------------------------------------------------------- /src/test/resources/uint8.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/uint8.mat -------------------------------------------------------------------------------- /src/test/resources/utf.m: -------------------------------------------------------------------------------- 1 | 2 | %% generate a curly d (U+0221) in UTF 8, 16, and 32 3 | val.utf8 = native2unicode(hex2dec(['F0'; 'A0'; '9C'; '8E'])', 'UTF-8'); 4 | val.utf16 = native2unicode(hex2dec(['D8'; '41'; 'DF'; '0E'])', 'UTF-16'); 5 | val.utf32 = native2unicode(hex2dec(['00'; '02'; '07'; '0E'])', 'UTF-32'); 6 | 7 | %% save it out to disk 8 | save('utf.mat', 'val') 9 | -------------------------------------------------------------------------------- /src/test/resources/utf.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diffplug/matfilerw/5edb6b223c77fe1dfdc5210f2078f94878d3f721/src/test/resources/utf.mat --------------------------------------------------------------------------------