Commit 884323ea authored by Peter Kriens's avatar Peter Kriens

mx memory

parent 5bdef29c
......@@ -7,4 +7,4 @@ jdk:
install: ./gradlew --version
script: ./gradlew --stacktrace build -i
script: ./gradlew -DGRADLE_OPTS=-Xmx500m --stacktrace build -i
// Available to customize the build
......@@ -2,8 +2,27 @@
# This file is left open for you to define your macros
#
src: src/main/java
bin: target/classes
testsrc: src/test/java
testbin: target/test-classes
target-dir: target
src: src/main/java
bin: target/classes
testsrc: src/test/java
testbin: target/test-classes
target-dir: target
javac.source: 1.8
javac.target: ${javac.source}
javac.compliance: ${javac.source}
javac.debug: on
Git-Descriptor: ${system-allow-fail;git describe --dirty --always}
Git-SHA: ${system-allow-fail;git rev-list -1 HEAD}
Bundle-Copyright: MIT
Bundle-Vendor: AlloyTools at Github
Bundle-DocURL: http://alloytools.org
Bundle-License: MIT
base.version: 5.0.0
Bundle-Version: ${base.version}.${tstamp}
-snapshot:
-groupid: org.alloytools
-pom: version=${versionmask;===s;${@version}}
This diff is collapsed.
eclipse.preferences.version=1
encoding/bnd.bnd=UTF-8
encoding/<project>=UTF-8
......@@ -22,109 +22,179 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.zip.Deflater;
/** Mutable; implements a growable array of bytes.
*
* <p> This class is more efficient than Java's ByteArrayOutputStream when writing large amount of data,
* because ByteArrayOutputStream will resize and copy entire existing contents every time the array needs to grow,
* whereas this class maintains a linked list of arrays (so when capacity is expanded we don't need to copy old data)
/**
* Mutable; implements a growable array of bytes.
* <p>
* This class is more efficient than Java's ByteArrayOutputStream when writing
* large amount of data, because ByteArrayOutputStream will resize and copy
* entire existing contents every time the array needs to grow, whereas this
* class maintains a linked list of arrays (so when capacity is expanded we
* don't need to copy old data)
*/
public final class ByteBuffer {
/** The size per chunk. */
private static final int SIZE = 65536;
/** The size per chunk. */
private static final int SIZE = 65536;
/** The list of chunks allocated so far; always has at least one chunk; every chunk is always exactly of size SIZE. */
private final LinkedList<byte[]> list = new LinkedList<byte[]>();
/**
* The list of chunks allocated so far; always has at least one chunk; every
* chunk is always exactly of size SIZE.
*/
private final LinkedList<byte[]> list = new LinkedList<byte[]>();
/** The number of bytes stored in the latest chunk; every chunk before that is always fully filled. */
private int n = 0;
/**
* The number of bytes stored in the latest chunk; every chunk before that
* is always fully filled.
*/
private int n = 0;
/** Construct an empty byte buffer. */
public ByteBuffer() { list.add(new byte[SIZE]); }
/** Construct an empty byte buffer. */
public ByteBuffer() {
list.add(new byte[SIZE]);
}
/** Write the given byte into this byte buffer. */
private ByteBuffer w(int b) {
if (n==SIZE) { list.add(new byte[SIZE]); n=0; }
byte[] array = list.getLast();
array[n] = (byte)b;
n++;
return this;
}
/** Write the given byte into this byte buffer. */
private ByteBuffer w(int b) {
if (n == SIZE) {
list.add(new byte[SIZE]);
n = 0;
}
byte[] array = list.getLast();
array[n] = (byte) b;
n++;
return this;
}
/** Write the given array of bytes into this byte buffer. */
private ByteBuffer write(byte[] b, int offset, int len) {
if (b==null || len<=0) return this; else if (n==SIZE) { list.add(new byte[SIZE]); n=0; }
while(true) { // loop invariant: len>0 and SIZE>n
byte[] array = list.getLast();
if (len <= (SIZE-n)) { System.arraycopy(b, offset, array, n, len); n += len; return this; }
System.arraycopy(b, offset, array, n, SIZE-n);
offset += (SIZE-n);
len -= (SIZE-n);
n = 0;
list.add(new byte[SIZE]);
}
}
/** Write the given array of bytes into this byte buffer. */
private ByteBuffer write(byte[] b, int offset, int len) {
if (b == null || len <= 0)
return this;
else if (n == SIZE) {
list.add(new byte[SIZE]);
n = 0;
}
while (true) { // loop invariant: len>0 and SIZE>n
byte[] array = list.getLast();
if (len <= (SIZE - n)) {
System.arraycopy(b, offset, array, n, len);
n += len;
return this;
}
System.arraycopy(b, offset, array, n, SIZE - n);
offset += (SIZE - n);
len -= (SIZE - n);
n = 0;
list.add(new byte[SIZE]);
}
}
/** Write the given String into this byte buffer (by converting the String into its UTF-8 representation) */
public ByteBuffer write(String string) {
if (string.length() == 0) return this;
byte[] b;
try { b = string.getBytes("UTF-8"); } catch(UnsupportedEncodingException ex) { return this; } // exception not possible
return write(b, 0, b.length);
}
/**
* Write the given String into this byte buffer (by converting the String
* into its UTF-8 representation)
*/
public ByteBuffer write(String string) {
if (string.length() == 0)
return this;
byte[] b;
try {
b = string.getBytes("UTF-8");
} catch (UnsupportedEncodingException ex) {
return this;
} // exception not possible
return write(b, 0, b.length);
}
/** Write the given number into this byte buffer, followed by a space. */
public ByteBuffer writes(long x) {
return write(Long.toString(x)).w(' ');
}
/** Write the given number into this byte buffer, followed by a space. */
public ByteBuffer writes(long x) {
return write(Long.toString(x)).w(' ');
}
/** Write the given number into this byte buffer (truncated to the range -32767..+32767), followed by a space. */
public strictfp ByteBuffer writes(double x) {
// These extreme values shouldn't happen, but we want to protect against them
if (Double.isNaN(x)) return write("0 "); else if (x>32767) return write("32767 "); else if (x<-32767) return write("-32767 ");
long num = (long)(x * 1000000);
if (num>=32767000000L) return write("32767 "); else if (num<=(-32767000000L)) return write("-32767 ");
// Now, regular doubles... let's allow up to 6 digits after the decimal point
if (num<0) { w('-'); num = -num; }
String str = Long.toString(num);
int len = str.length();
if (len<=6) {
w('.');
while(len<6) { w('0'); len++; }
return write(str).w(' ');
}
return write(str.substring(0, str.length()-6)).w('.').write(str.substring(str.length()-6)).w(' ');
}
/**
* Write the given number into this byte buffer (truncated to the range
* -32767..+32767), followed by a space.
*/
public strictfp ByteBuffer writes(double x) {
// These extreme values shouldn't happen, but we want to protect against
// them
if (Double.isNaN(x))
return write("0 ");
else if (x > 32767)
return write("32767 ");
else if (x < -32767)
return write("-32767 ");
long num = (long) (x * 1000000);
if (num >= 32767000000L)
return write("32767 ");
else if (num <= (-32767000000L))
return write("-32767 ");
// Now, regular doubles... let's allow up to 6 digits after the decimal
// point
if (num < 0) {
w('-');
num = -num;
}
String str = Long.toString(num);
int len = str.length();
if (len <= 6) {
w('.');
while (len < 6) {
w('0');
len++;
}
return write(str).w(' ');
}
return write(str.substring(0, str.length() - 6)).w('.').write(str.substring(str.length() - 6)).w(' ');
}
/** Write the entire content into the given file using Flate compression (see RFC1951) then return the number of bytes written. */
public long dumpFlate(RandomAccessFile os) throws IOException {
Deflater zip = new Deflater(Deflater.BEST_COMPRESSION);
byte[] output = new byte[8192];
Iterator<byte[]> it = list.iterator(); // when null, that means we have told the Deflater that no more input would be coming
long ans = 0; // the number of bytes written out so far
while(true) {
if (it!=null && zip.needsInput() && it.hasNext()) {
byte[] in = it.next();
if (in == list.getLast()) { zip.setInput(in, 0, n); it=null; zip.finish(); } else { zip.setInput(in, 0, SIZE); }
}
if (it==null && zip.finished()) break;
int count = zip.deflate(output);
if (count > 0) {
ans = ans + count;
if (ans < 0) throw new IOException("Data too large to be written to the output file.");
os.write(output, 0, count);
}
}
return ans;
}
/**
* Write the entire content into the given file using Flate compression (see
* RFC1951) then return the number of bytes written.
*/
public long dumpFlate(RandomAccessFile os) throws IOException {
Deflater zip = new Deflater(Deflater.BEST_COMPRESSION);
byte[] output = new byte[8192];
Iterator<byte[]> it = list.iterator(); // when null, that means we have
// told the Deflater that no
// more input would be coming
long ans = 0; // the number of bytes written out so far
while (true) {
if (it != null && zip.needsInput() && it.hasNext()) {
byte[] in = it.next();
if (in == list.getLast()) {
zip.setInput(in, 0, n);
it = null;
zip.finish();
} else {
zip.setInput(in, 0, SIZE);
}
}
if (it == null && zip.finished())
break;
int count = zip.deflate(output);
if (count > 0) {
ans = ans + count;
if (ans < 0)
throw new IOException("Data too large to be written to the output file.");
os.write(output, 0, count);
}
}
return ans;
}
/** Write the entire content into the given file as-is, then return the number of bytes written. */
public long dump(RandomAccessFile os) throws IOException {
if (list.size() >= (Long.MAX_VALUE / SIZE)) throw new IOException("Data too large to be written to the output file.");
byte[] last = list.getLast();
for(byte[] x: list) if (x!=last) os.write(x);
if (n>0) os.write(last, 0, n);
return ((long)(list.size()-1)) * SIZE + n;
}
/**
* Write the entire content into the given file as-is, then return the
* number of bytes written.
*/
public long dump(RandomAccessFile os) throws IOException {
if (list.size() >= (Long.MAX_VALUE / SIZE))
throw new IOException("Data too large to be written to the output file.");
byte[] last = list.getLast();
for (byte[] x : list)
if (x != last)
os.write(x);
if (n > 0)
os.write(last, 0, n);
return ((long) (list.size() - 1)) * SIZE + n;
}
}
......@@ -15,12 +15,17 @@
package edu.mit.csail.sdg.alloy4;
/** This defines a compute() method that takes an Object input and produces a String output. */
/**
* This defines a compute() method that takes an Object input and produces a
* String output.
*/
public interface Computer {
/** This method takes an Object input and produces a String output.
* @throws Exception if an error occurred during the computation.
*/
public String compute (Object input) throws Exception;
/**
* This method takes an Object input and produces a String output.
*
* @throws Exception if an error occurred during the computation.
*/
public String compute(Object input) throws Exception;
}
......@@ -24,60 +24,100 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.io.Serializable;
/** Immutable; implements a map based on hashCode() and equals(); null key and values are allowed.
/**
* Immutable; implements a map based on hashCode() and equals(); null key and
* values are allowed.
*
* @param <K> - the type of key
* @param <V> - the type of value
*/
public final class ConstMap<K,V> extends AbstractMap<K,V> implements Serializable {
/** This ensures this class can be serialized reliably. */
private static final long serialVersionUID = 0;
/** The underlying Collections.unmodifiableMap map. */
private final Map<K,V> map;
/** This caches a read-only empty map. */
private static final ConstMap<Object,Object> emptymap = new ConstMap<Object,Object>(new HashMap<Object,Object>(0));
/** Constructs an unmodifiable map with the given map as the backing store. */
private ConstMap(Map<? extends K,? extends V> map) {
this.map = Collections.unmodifiableMap(map);
}
/** Returns an unmodifiable empty map. */
@SuppressWarnings("unchecked")
public static<K,V> ConstMap<K,V> make() {
return (ConstMap<K,V>) emptymap;
}
/** Returns an unmodifiable map with the same entries and traversal order as the given map.
* (If map==null, we'll return an unmodifiable empty map)
*/
public static<K,V> ConstMap<K,V> make(Map<K,V> map) {
if (map instanceof ConstMap) return (ConstMap<K,V>)map;
if (map == null || map.isEmpty()) return make(); else return new ConstMap<K,V>(new LinkedHashMap<K,V>(map));
}
/** Returns an unmodifiable view of the mappings in this map. */
@Override public Set<Map.Entry<K,V>> entrySet() { return map.entrySet(); }
/** Returns an unmodifiable view of the keys in this map. */
@Override public Set<K> keySet() { return map.keySet(); } // overridden for performance
/** Returns an unmodifiable view of the values in this map. */
@Override public Collection<V> values() { return map.values(); } // overridden for performance
/** Returns the number of (key, value) mapping in this map. */
@Override public int size() { return map.size(); } // overridden for performance
/** Returns true if exists at least one (k, v) mapping where (k==null ? key==null : k.equals(key)) */
@Override public boolean containsKey(Object key) { return map.containsKey(key); } // overridden for performance
/** Returns true if exists at least one (k, v) mapping where (v==null ? value==null : v.equals(value)) */
@Override public boolean containsValue(Object value) { return map.containsValue(value); } // overridden for performance
/** Returns the value associated with the key (or null if not found); null is also returned if the given key maps to null. */
@Override public V get(Object key) { return map.get(key); } // overridden for performance
public final class ConstMap<K, V> extends AbstractMap<K,V> implements Serializable {
/** This ensures this class can be serialized reliably. */
private static final long serialVersionUID = 0;
/** The underlying Collections.unmodifiableMap map. */
private final Map<K,V> map;
/** This caches a read-only empty map. */
private static final ConstMap<Object,Object> emptymap = new ConstMap<Object,Object>(
new HashMap<Object,Object>(0));
/**