Revamped iterating over arrays to be GWT-compatible.

We no longer use reflection for any of that; we have a suite of primitive array
helpers that do what is needed.
This commit is contained in:
Michael Bayne
2015-09-21 16:01:38 -07:00
parent cbd80d1d08
commit ec7ea6a660
3 changed files with 49 additions and 56 deletions
@@ -3,9 +3,7 @@
package com.samskivert.mustache; package com.samskivert.mustache;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
/** /**
@@ -13,17 +11,6 @@ import java.util.Map;
*/ */
public class DefaultCollector extends BasicCollector public class DefaultCollector extends BasicCollector
{ {
@Override
public Iterator<?> toIterator (final Object value) {
Iterator<?> iter = super.toIterator(value);
if (iter != null) return iter;
if (value.getClass().isArray()) {
return Arrays.asList((Object[])value).iterator();
}
return null;
}
@Override @Override
public <K,V> Map<K,V> createFetcherCache () { public <K,V> Map<K,V> createFetcherCache () {
return new HashMap<K,V>(); return new HashMap<K,V>();
@@ -22,6 +22,15 @@ public abstract class BasicCollector implements Mustache.Collector
if (value instanceof Iterator<?>) { if (value instanceof Iterator<?>) {
return (Iterator<?>)value; return (Iterator<?>)value;
} }
if (value.getClass().isArray()) {
final ArrayHelper helper = arrayHelper(value);
return new Iterator<Object>() {
private int _count = helper.length(value), _idx;
@Override public boolean hasNext () { return _idx < _count; }
@Override public Object next () { return helper.get(value, _idx++); }
@Override public void remove () { throw new UnsupportedOperationException(); }
};
}
return null; return null;
} }
@@ -36,15 +45,7 @@ public abstract class BasicCollector implements Mustache.Collector
if (c >= '0' && c <= '9') { if (c >= '0' && c <= '9') {
if (ctx instanceof List<?>) return LIST_FETCHER; if (ctx instanceof List<?>) return LIST_FETCHER;
if (ctx instanceof Iterator<?>) return ITER_FETCHER; if (ctx instanceof Iterator<?>) return ITER_FETCHER;
if (ctx instanceof Object[]) return OBJECT_ARRAY_FETCHER; if (ctx.getClass().isArray()) return arrayHelper(ctx);
if (ctx instanceof boolean[]) return BOOLEAN_ARRAY_FETCHER;
if (ctx instanceof byte[]) return BYTE_ARRAY_FETCHER;
if (ctx instanceof char[]) return CHAR_ARRAY_FETCHER;
if (ctx instanceof short[]) return SHORT_ARRAY_FETCHER;
if (ctx instanceof int[]) return INT_ARRAY_FETCHER;
if (ctx instanceof long[]) return LONG_ARRAY_FETCHER;
if (ctx instanceof float[]) return FLOAT_ARRAY_FETCHER;
if (ctx instanceof double[]) return DOUBLE_ARRAY_FETCHER;
} }
return null; return null;
@@ -54,6 +55,19 @@ public abstract class BasicCollector implements Mustache.Collector
* a standard {@link Map} implementation or something like {@code ConcurrentHashMap}. */ * a standard {@link Map} implementation or something like {@code ConcurrentHashMap}. */
public abstract <K,V> Map<K,V> createFetcherCache (); public abstract <K,V> Map<K,V> createFetcherCache ();
protected static ArrayHelper arrayHelper (Object ctx) {
if (ctx instanceof Object[]) return OBJECT_ARRAY_HELPER;
if (ctx instanceof boolean[]) return BOOLEAN_ARRAY_HELPER;
if (ctx instanceof byte[]) return BYTE_ARRAY_HELPER;
if (ctx instanceof char[]) return CHAR_ARRAY_HELPER;
if (ctx instanceof short[]) return SHORT_ARRAY_HELPER;
if (ctx instanceof int[]) return INT_ARRAY_HELPER;
if (ctx instanceof long[]) return LONG_ARRAY_HELPER;
if (ctx instanceof float[]) return FLOAT_ARRAY_HELPER;
if (ctx instanceof double[]) return DOUBLE_ARRAY_HELPER;
return null;
}
protected static final Mustache.VariableFetcher MAP_FETCHER = new Mustache.VariableFetcher() { protected static final Mustache.VariableFetcher MAP_FETCHER = new Mustache.VariableFetcher() {
public Object get (Object ctx, String name) throws Exception { public Object get (Object ctx, String name) throws Exception {
Map<?,?> map = (Map<?,?>)ctx; Map<?,?> map = (Map<?,?>)ctx;
@@ -87,7 +101,13 @@ public abstract class BasicCollector implements Mustache.Collector
} }
}; };
protected static abstract class ArrayFetcher implements Mustache.VariableFetcher { protected static final Mustache.VariableFetcher THIS_FETCHER = new Mustache.VariableFetcher() {
public Object get (Object ctx, String name) throws Exception {
return ctx;
}
};
protected static abstract class ArrayHelper implements Mustache.VariableFetcher {
public Object get (Object ctx, String name) throws Exception { public Object get (Object ctx, String name) throws Exception {
try { try {
return get(ctx, Integer.parseInt(name)); return get(ctx, Integer.parseInt(name));
@@ -97,40 +117,44 @@ public abstract class BasicCollector implements Mustache.Collector
return Template.NO_FETCHER_FOUND; return Template.NO_FETCHER_FOUND;
} }
} }
public abstract int length (Object ctx);
protected abstract Object get (Object ctx, int index); protected abstract Object get (Object ctx, int index);
} }
protected static final ArrayFetcher OBJECT_ARRAY_FETCHER = new ArrayFetcher() { protected static final ArrayHelper OBJECT_ARRAY_HELPER = new ArrayHelper() {
@Override protected Object get (Object ctx, int index) { return ((Object[])ctx)[index]; } @Override protected Object get (Object ctx, int index) { return ((Object[])ctx)[index]; }
@Override public int length (Object ctx) { return ((Object[])ctx).length; }
}; };
protected static final ArrayFetcher BOOLEAN_ARRAY_FETCHER = new ArrayFetcher() { protected static final ArrayHelper BOOLEAN_ARRAY_HELPER = new ArrayHelper() {
@Override protected Object get (Object ctx, int index) { return ((boolean[])ctx)[index]; } @Override protected Object get (Object ctx, int index) { return ((boolean[])ctx)[index]; }
@Override public int length (Object ctx) { return ((boolean[])ctx).length; }
}; };
protected static final ArrayFetcher BYTE_ARRAY_FETCHER = new ArrayFetcher() { protected static final ArrayHelper BYTE_ARRAY_HELPER = new ArrayHelper() {
@Override protected Object get (Object ctx, int index) { return ((byte[])ctx)[index]; } @Override protected Object get (Object ctx, int index) { return ((byte[])ctx)[index]; }
@Override public int length (Object ctx) { return ((byte[])ctx).length; }
}; };
protected static final ArrayFetcher CHAR_ARRAY_FETCHER = new ArrayFetcher() { protected static final ArrayHelper CHAR_ARRAY_HELPER = new ArrayHelper() {
@Override protected Object get (Object ctx, int index) { return ((char[])ctx)[index]; } @Override protected Object get (Object ctx, int index) { return ((char[])ctx)[index]; }
@Override public int length (Object ctx) { return ((char[])ctx).length; }
}; };
protected static final ArrayFetcher SHORT_ARRAY_FETCHER = new ArrayFetcher() { protected static final ArrayHelper SHORT_ARRAY_HELPER = new ArrayHelper() {
@Override protected Object get (Object ctx, int index) { return ((short[])ctx)[index]; } @Override protected Object get (Object ctx, int index) { return ((short[])ctx)[index]; }
@Override public int length (Object ctx) { return ((short[])ctx).length; }
}; };
protected static final ArrayFetcher INT_ARRAY_FETCHER = new ArrayFetcher() { protected static final ArrayHelper INT_ARRAY_HELPER = new ArrayHelper() {
@Override protected Object get (Object ctx, int index) { return ((int[])ctx)[index]; } @Override protected Object get (Object ctx, int index) { return ((int[])ctx)[index]; }
@Override public int length (Object ctx) { return ((int[])ctx).length; }
}; };
protected static final ArrayFetcher LONG_ARRAY_FETCHER = new ArrayFetcher() { protected static final ArrayHelper LONG_ARRAY_HELPER = new ArrayHelper() {
@Override protected Object get (Object ctx, int index) { return ((long[])ctx)[index]; } @Override protected Object get (Object ctx, int index) { return ((long[])ctx)[index]; }
@Override public int length (Object ctx) { return ((long[])ctx).length; }
}; };
protected static final ArrayFetcher FLOAT_ARRAY_FETCHER = new ArrayFetcher() { protected static final ArrayHelper FLOAT_ARRAY_HELPER = new ArrayHelper() {
@Override protected Object get (Object ctx, int index) { return ((float[])ctx)[index]; } @Override protected Object get (Object ctx, int index) { return ((float[])ctx)[index]; }
@Override public int length (Object ctx) { return ((float[])ctx).length; }
}; };
protected static final ArrayFetcher DOUBLE_ARRAY_FETCHER = new ArrayFetcher() { protected static final ArrayHelper DOUBLE_ARRAY_HELPER = new ArrayHelper() {
@Override protected Object get (Object ctx, int index) { return ((double[])ctx)[index]; } @Override protected Object get (Object ctx, int index) { return ((double[])ctx)[index]; }
}; @Override public int length (Object ctx) { return ((double[])ctx).length; }
protected static final Mustache.VariableFetcher THIS_FETCHER = new Mustache.VariableFetcher() {
public Object get (Object ctx, String name) throws Exception {
return ctx;
}
}; };
} }
@@ -20,24 +20,6 @@ import java.util.concurrent.ConcurrentHashMap;
*/ */
public class DefaultCollector extends BasicCollector public class DefaultCollector extends BasicCollector
{ {
@Override
public Iterator<?> toIterator (final Object value) {
Iterator<?> iter = super.toIterator(value);
if (iter != null) return iter;
if (value.getClass().isArray()) {
return new AbstractList<Object>() {
public int size () {
return Array.getLength(value);
}
public Object get (int idx) {
return Array.get(value, idx);
}
}.iterator();
}
return null;
}
@Override @Override
public Mustache.VariableFetcher createFetcher (Object ctx, String name) { public Mustache.VariableFetcher createFetcher (Object ctx, String name) {
Mustache.VariableFetcher fetcher = super.createFetcher(ctx, name); Mustache.VariableFetcher fetcher = super.createFetcher(ctx, name);