Warning : session_start(): open(/var/lib/php/sessions/sess_jcod3sjmmin1l0br7s0u3qvhjp, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning : session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
import java.util.*;
import java.util.zip.*;
import java.util.List;
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
import java.util.function.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.table.*;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.lang.ref.*;
import java.lang.management.*;
import java.security.*;
import java.security.spec.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.imageio.*;
import java.math.*;
import static x30_pkg.x30_util.DynamicObject;
import java.awt.image.DataBufferByte;
import java.awt.geom.*;
import java.text.*;
import java.text.NumberFormat;
import java.awt.datatransfer.StringSelection;
import java.util.TimeZone;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.nio.file.Path;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
class main {
static void g22_runPostAnalysisLeftArrowScript(Gazelle22_ImageToRegions itr,
GazelleV_LeftArrowScript.Script script) {
if (script == null) return;
// def score region { ... }
var fScore = script.getFunction("score");
if (fScore != null) {
List> regions = itr.regions.regions();
int n = l(regions);
Map, Double> scores = new HashMap();
for (var region : regions)
scores.put(region, toDouble(fScore.call(null, region)));
itr.scoredRegions = mapSortedByValue(scores);
}
}
static int l(Object[] a) { return a == null ? 0 : a.length; }
static int l(boolean[] a) { return a == null ? 0 : a.length; }
static int l(byte[] a) { return a == null ? 0 : a.length; }
static int l(short[] a) { return a == null ? 0 : a.length; }
static int l(long[] a) { return a == null ? 0 : a.length; }
static int l(int[] a) { return a == null ? 0 : a.length; }
static int l(float[] a) { return a == null ? 0 : a.length; }
static int l(double[] a) { return a == null ? 0 : a.length; }
static int l(char[] a) { return a == null ? 0 : a.length; }
static int l(Collection c) { return c == null ? 0 : c.size(); }
static int l(Iterator i) { return iteratorCount_int_close(i); } // consumes the iterator && closes it if possible
static int l(Map m) { return m == null ? 0 : m.size(); }
static int l(CharSequence s) { return s == null ? 0 : s.length(); }
static long l(File f) { return f == null ? 0 : f.length(); }
static int l(Object o) {
return o == null ? 0
: o instanceof String ? l((String) o)
: o instanceof Map ? l((Map) o)
: o instanceof Collection ? l((Collection) o)
: o instanceof Object[] ? l((Object[]) o)
: o instanceof boolean[] ? l((boolean[]) o)
: o instanceof byte[] ? l((byte[]) o)
: o instanceof char[] ? l((char[]) o)
: o instanceof short[] ? l((short[]) o)
: o instanceof int[] ? l((int[]) o)
: o instanceof float[] ? l((float[]) o)
: o instanceof double[] ? l((double[]) o)
: o instanceof long[] ? l((long[]) o)
: (Integer) call(o, "size");
}
static int l(MultiSet ms) { return ms == null ? 0 : ms.size(); }
static int l(IntRange r) { return r == null ? 0 : r.length(); }
static double l(DoubleRange r) { return r == null ? 0 : r.length(); }
static int l(IntBuffer b) { return b == null ? 0 : b.size(); }
static int l(AppendableChain a) { return a == null ? 0 : a.size; }
static double toDouble(Object o) {
if (o instanceof Number)
return ((Number) o).doubleValue();
if (o instanceof BigInteger)
return ((BigInteger) o).doubleValue();
if (o instanceof String)
return parseDouble((String) o);
if (o == null) return 0.0;
throw fail(o);
}
static LinkedHashMap mapSortedByValue(Map map) {
return orderMapByValue(map);
}
static int iteratorCount_int_close(Iterator i) { try {
int n = 0;
if (i != null) while (i.hasNext()) { i.next(); ++n; }
if (i instanceof AutoCloseable) ((AutoCloseable) i).close();
return n;
} catch (Exception __e) { throw rethrow(__e); } }
static Object call(Object o) {
return callF(o);
}
// varargs assignment fixer for a single string array argument
static Object call(Object o, String method, String[] arg) {
return call(o, method, new Object[] {arg});
}
static Object call(Object o, String method, Object... args) {
//ret call_cached(o, method, args);
return call_withVarargs(o, method, args);
}
static double parseDouble(String s) {
return empty(s) ? 0.0 : Double.parseDouble(s);
}
static RuntimeException fail() { throw new RuntimeException("fail"); }
static RuntimeException fail(Throwable e) { throw asRuntimeException(e); }
static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); }
static RuntimeException fail(Object... objects) { throw new Fail(objects); }
static RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); }
static RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); }
static LinkedHashMap orderMapByValue(final Map map) {
List l = new ArrayList(map.keySet());
sort(l, mapComparator(map));
LinkedHashMap map2 = litorderedmap();
for (A a : l)
map2.put(a, map.get(a));
return map2;
}
static RuntimeException rethrow(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static RuntimeException rethrow(String msg, Throwable t) {
throw new RuntimeException(msg, t);
}
static Map> callF_cache = newDangerousWeakHashMap();
static A callF(F0 f) {
return f == null ? null : f.get();
}
static B callF(F1 f, A a) {
return f == null ? null : f.get(a);
}
static A callF(IF0 f) {
return f == null ? null : f.get();
}
static B callF(IF1 f, A a) {
return f == null ? null : f.get(a);
}
static B callF(A a, IF1 f) {
return f == null ? null : f.get(a);
}
static C callF(IF2 f, A a, B b) {
return f == null ? null : f.get(a, b);
}
static void callF(VF1 f, A a) {
if (f != null) f.get(a);
}
static void callF(A a, IVF1 f) {
if (f != null) f.get(a);
}
static void callF(IVF1 f, A a) {
if (f != null) f.get(a);
}
static Object callF(Runnable r) { { if (r != null) r.run(); } return null; }
static Object callF(Object f, Object... args) {
return safeCallF(f, args);
}
static Object safeCallF(Object f, Object... args) {
if (f instanceof Runnable) {
((Runnable) f).run();
return null;
}
if (f == null) return null;
Class c = f.getClass();
ArrayList methods;
synchronized(callF_cache) {
methods = callF_cache.get(c);
if (methods == null)
methods = callF_makeCache(c);
}
int n = l(methods);
if (n == 0) {
if (f instanceof String)
throw fail("Legacy call: " + f);
throw fail("No get method in " + getClassName(c));
}
if (n == 1) return invokeMethod(methods.get(0), f, args);
for (int i = 0; i < n; i++) {
Method m = methods.get(i);
if (call_checkArgs(m, args, false))
return invokeMethod(m, f, args);
}
throw fail("No matching get method in " + getClassName(c));
}
// used internally
static ArrayList callF_makeCache(Class c) {
ArrayList l = new ArrayList();
Class _c = c;
do {
for (Method m : _c.getDeclaredMethods())
if (m.getName().equals("get")) {
makeAccessible(m);
l.add(m);
}
if (!l.isEmpty()) break;
_c = _c.getSuperclass();
} while (_c != null);
callF_cache.put(c, l);
return l;
}
static Object call_withVarargs(Object o, String method, Object... args) { try {
if (o == null) return null;
if (o instanceof Class) {
Class c = (Class) o;
_MethodCache cache = callOpt_getCache(c);
Method me = cache.findStaticMethod(method, args);
if (me != null)
return invokeMethod(me, null, args);
// try varargs
List methods = cache.cache.get(method);
if (methods != null) methodSearch: for (Method m : methods) {
{ if (!(m.isVarArgs())) continue; }
{ if (!(isStaticMethod(m))) continue; }
Object[] newArgs = massageArgsForVarArgsCall(m, args);
if (newArgs != null)
return invokeMethod(m, null, newArgs);
}
throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found");
} else {
Class c = o.getClass();
_MethodCache cache = callOpt_getCache(c);
Method me = cache.findMethod(method, args);
if (me != null)
return invokeMethod(me, o, args);
// try varargs
List methods = cache.cache.get(method);
if (methods != null) methodSearch: for (Method m : methods) {
{ if (!(m.isVarArgs())) continue; }
Object[] newArgs = massageArgsForVarArgsCall(m, args);
if (newArgs != null)
return invokeMethod(m, o, newArgs);
}
throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found");
}
} catch (Exception __e) { throw rethrow(__e); } }
static boolean empty(Collection c) { return c == null || c.isEmpty(); }
static boolean empty(Iterable c) { return c == null || !c.iterator().hasNext(); }
static boolean empty(CharSequence s) { return s == null || s.length() == 0; }
static boolean empty(Map map) { return map == null || map.isEmpty(); }
static boolean empty(Object[] o) { return o == null || o.length == 0; }
static boolean empty(BitSet bs) { return bs == null || bs.isEmpty(); }
static boolean empty(Object o) {
if (o instanceof Collection) return empty((Collection) o);
if (o instanceof String) return empty((String) o);
if (o instanceof Map) return empty((Map) o);
if (o instanceof Object[]) return empty((Object[]) o);
if (o instanceof byte[]) return empty((byte[]) o);
if (o == null) return true;
throw fail("unknown type for 'empty': " + getType(o));
}
static boolean empty(Iterator i) { return i == null || !i.hasNext(); }
static boolean empty(double[] a) { return a == null || a.length == 0; }
static boolean empty(float[] a) { return a == null || a.length == 0; }
static boolean empty(int[] a) { return a == null || a.length == 0; }
static boolean empty(long[] a) { return a == null || a.length == 0; }
static boolean empty(byte[] a) { return a == null || a.length == 0; }
static boolean empty(short[] a) { return a == null || a.length == 0; }
static boolean empty(MultiSet ms) { return ms == null || ms.isEmpty(); }
static boolean empty(MultiMap mm) { return mm == null || mm.isEmpty(); }
static boolean empty(File f) { return getFileSize(f) == 0; }
static boolean empty(IntRange r) { return r == null || r.empty(); }
static boolean empty(DoubleRange r) { return r == null || r.isEmpty(); }
static boolean empty(IntBuffer b) { return b == null || b.isEmpty(); }
static boolean empty(Rect r) { return !(r != null && r.w != 0 && r.h != 0); }
static boolean empty(Chain c) { return c == null; }
static boolean empty(AppendableChain c) { return c == null; }
static RuntimeException asRuntimeException(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static void sort(T[] a, Comparator super T> c) {
if (a != null) Arrays.sort(a, c);
}
static void sort(T[] a) {
if (a != null) Arrays.sort(a);
}
static void sort(int[] a) { if (a != null) Arrays.sort(a); }
static void sort(List a, Comparator super T> c) {
if (a != null) Collections.sort(a, c);
}
static void sort(List a) {
if (a != null) Collections.sort(a);
}
static Comparator mapComparator(final Map map) {
return new Comparator () {
public int compare(A a, A b) {
return cmp(map.get(a), map.get(b));
}
};
}
static LinkedHashMap litorderedmap(Object... x) {
LinkedHashMap map = new LinkedHashMap();
litmap_impl(map, x);
return map;
}
static void _handleError(Error e) {
call(javax(), "_handleError", e);
}
static Map newDangerousWeakHashMap() {
return _registerDangerousWeakMap(synchroMap(new WeakHashMap()));
}
// initFunction: voidfunc(Map) - is called initially, and after clearing the map
static Map newDangerousWeakHashMap(Object initFunction) {
return _registerDangerousWeakMap(synchroMap(new WeakHashMap()), initFunction);
}
static String getClassName(Object o) {
return o == null ? "null" : o instanceof Class ? ((Class) o).getName() : o.getClass().getName();
}
static Object invokeMethod(Method m, Object o, Object... args) { try {
try {
return m.invoke(o, args);
} catch (InvocationTargetException e) {
throw rethrow(getExceptionCause(e));
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(e.getMessage() + " - was calling: " + m + ", args: " + joinWithSpace(classNames(args)));
}
} catch (Exception __e) { throw rethrow(__e); } }
static boolean call_checkArgs(Method m, Object[] args, boolean debug) {
Class>[] types = m.getParameterTypes();
if (types.length != args.length) {
if (debug)
print("Bad parameter length: " + args.length + " vs " + types.length);
return false;
}
for (int i = 0; i < types.length; i++) {
Object arg = args[i];
if (!(arg == null ? !types[i].isPrimitive()
: isInstanceX(types[i], arg))) {
if (debug)
print("Bad parameter " + i + ": " + arg + " vs " + types[i]);
return false;
}
}
return true;
}
static Field makeAccessible(Field f) {
try {
f.setAccessible(true);
} catch (Throwable e) {
// Note: The error reporting only works with Java VM option --illegal-access=deny
vmBus_send("makeAccessible_error", e, f);
}
return f;
}
static Method makeAccessible(Method m) {
try {
m.setAccessible(true);
} catch (Throwable e) {
vmBus_send("makeAccessible_error", e, m);
}
return m;
}
static Constructor makeAccessible(Constructor c) {
try {
c.setAccessible(true);
} catch (Throwable e) {
vmBus_send("makeAccessible_error", e, c);
}
return c;
}
static final Map callOpt_cache = newDangerousWeakHashMap();
static Object callOpt_cached(Object o, String methodName, Object... args) { try {
if (o == null) return null;
if (o instanceof Class) {
Class c = (Class) o;
_MethodCache cache = callOpt_getCache(c);
// TODO: (super-rare) case where method exists static and non-static
// with different args
Method me = cache.findMethod(methodName, args);
if (me == null || (me.getModifiers() & Modifier.STATIC) == 0) return null;
return invokeMethod(me, null, args);
} else {
Class c = o.getClass();
_MethodCache cache = callOpt_getCache(c);
Method me = cache.findMethod(methodName, args);
if (me == null) return null;
return invokeMethod(me, o, args);
}
} catch (Exception __e) { throw rethrow(__e); } }
// no longer synchronizes! (see #1102990)
static _MethodCache callOpt_getCache(Class c) {
_MethodCache cache = callOpt_cache.get(c);
if (cache == null)
callOpt_cache.put(c, cache = new _MethodCache(c));
return cache;
}
static boolean isStaticMethod(Method m) {
return methodIsStatic(m);
}
static Object[] massageArgsForVarArgsCall(Method m, Object[] args) {
Class>[] types = m.getParameterTypes();
int n = types.length-1, nArgs = args.length;
if (nArgs < n) return null;
for (int i = 0; i < n; i++)
if (!argumentCompatibleWithType(args[i], types[i]))
return null;
Class varArgType = types[n].getComponentType();
for (int i = n; i < nArgs; i++)
if (!argumentCompatibleWithType(args[i], varArgType))
return null;
Object[] newArgs = new Object[n+1];
arraycopy(args, 0, newArgs, 0, n);
Object[] varArgs = arrayOfType(varArgType, nArgs-n);
arraycopy(args, n, varArgs, 0, nArgs-n);
newArgs[n] = varArgs;
return newArgs;
}
static String joinWithComma(Collection c) {
return join(", ", c);
}
static String joinWithComma(Object... c) {
return join(", ", c);
}
static String joinWithComma(String... c) {
return join(", ", c);
}
static String joinWithComma(Pair p) {
return p == null ? "" : joinWithComma(str(p.a), str(p.b));
}
static List classNames(Collection l) {
return getClassNames(l);
}
static List classNames(Object[] l) {
return getClassNames(Arrays.asList(l));
}
static String getType(Object o) {
return getClassName(o);
}
static long getFileSize(String path) {
return path == null ? 0 : new File(path).length();
}
static long getFileSize(File f) {
return f == null ? 0 : f.length();
}
static int cmp(Number a, Number b) {
return a == null ? b == null ? 0 : -1 : cmp(a.doubleValue(), b.doubleValue());
}
static int cmp(double a, double b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static int cmp(int a, int b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static int cmp(long a, long b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static int cmp(Object a, Object b) {
if (a == null) return b == null ? 0 : -1;
if (b == null) return 1;
return ((Comparable) a).compareTo(b);
}
static HashMap litmap(Object... x) {
HashMap map = new HashMap();
litmap_impl(map, x);
return map;
}
static void litmap_impl(Map map, Object... x) {
if (x != null) for (int i = 0; i < x.length-1; i += 2)
if (x[i+1] != null)
map.put(x[i], x[i+1]);
}
static Class javax() {
return getJavaX();
}
static List _registerDangerousWeakMap_preList;
static A _registerDangerousWeakMap(A map) {
return _registerDangerousWeakMap(map, null);
}
static A _registerDangerousWeakMap(A map, Object init) {
callF(init, map);
if (init instanceof String) {
final String f = (String) init;
init = new VF1() { public void get(Map map) { try { callMC(f, map) ; } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "callMC(f, map)"; }};
}
if (javax() == null) {
// We're in class init
if (_registerDangerousWeakMap_preList == null) _registerDangerousWeakMap_preList = synchroList();
_registerDangerousWeakMap_preList.add(pair(map, init));
return map;
}
call(javax(), "_registerDangerousWeakMap", map, init);
return map;
}
static void _onLoad_registerDangerousWeakMap() {
assertNotNull(javax());
if (_registerDangerousWeakMap_preList == null) return;
for (Pair p : _registerDangerousWeakMap_preList)
_registerDangerousWeakMap(p.a, p.b);
_registerDangerousWeakMap_preList = null;
}
static Map synchroMap() {
return synchroHashMap();
}
static Map synchroMap(Map map) {
return Collections.synchronizedMap(map);
}
static Throwable getExceptionCause(Throwable e) {
Throwable c = e.getCause();
return c != null ? c : e;
}
static String joinWithSpace(Iterable c) {
return join(" ", c);
}
static String joinWithSpace(String... c) {
return join(" ", c);
}
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
static boolean printAlsoToSystemOut = true;
static volatile Appendable print_log = local_log; // might be redirected, e.g. to main bot
// in bytes - will cut to half that
static volatile int print_log_max = 1024*1024;
static volatile int local_log_max = 100*1024;
static boolean print_silent = false; // total mute if set
static Object print_byThread_lock = new Object();
static volatile ThreadLocal print_byThread; // special handling by thread - prefers F1
static volatile Object print_allThreads;
static volatile Object print_preprocess;
static void print() {
print("");
}
static A print(String s, A o) {
print(combinePrintParameters(s, o));
return o;
}
// slightly overblown signature to return original object...
static A print(A o) {
ping_okInCleanUp();
if (print_silent) return o;
String s = o + "\n";
print_noNewLine(s);
return o;
}
static void print_noNewLine(String s) {
try {
Object f = getThreadLocal(print_byThread_dontCreate());
if (f == null) f = print_allThreads;
if (f != null)
// We do need the general callF machinery here as print_byThread is sometimes shared between modules
if (isFalse(
f instanceof F1 ? ((F1) f).get(s) :
callF(f, s))) return;
} catch (Throwable e) {
System.out.println(getStackTrace(e));
}
print_raw(s);
}
static void print_raw(String s) {
if (print_preprocess != null) s = (String) callF(print_preprocess, s);
s = fixNewLines(s);
Appendable loc = local_log;
Appendable buf = print_log;
int loc_max = print_log_max;
if (buf != loc && buf != null) {
print_append(buf, s, print_log_max);
loc_max = local_log_max;
}
if (loc != null)
print_append(loc, s, loc_max);
if (printAlsoToSystemOut)
System.out.print(s);
vmBus_send("printed", mc(), s);
}
static void print_autoRotate() {
}
static boolean isInstanceX(Class type, Object arg) {
if (type == boolean.class) return arg instanceof Boolean;
if (type == int.class) return arg instanceof Integer;
if (type == long.class) return arg instanceof Long;
if (type == float.class) return arg instanceof Float;
if (type == short.class) return arg instanceof Short;
if (type == char.class) return arg instanceof Character;
if (type == byte.class) return arg instanceof Byte;
if (type == double.class) return arg instanceof Double;
return type.isInstance(arg);
}
static void vmBus_send(String msg, Object... args) {
Object arg = vmBus_wrapArgs(args);
pcallFAll_minimalExceptionHandling(vm_busListeners_live(), msg, arg);
pcallFAll_minimalExceptionHandling(vm_busListenersByMessage_live().get(msg), msg, arg);
}
static void vmBus_send(String msg) {
vmBus_send(msg, (Object) null);
}
static boolean methodIsStatic(Method m) {
return (m.getModifiers() & Modifier.STATIC) != 0;
}
static boolean argumentCompatibleWithType(Object arg, Class type) {
return arg == null ? !type.isPrimitive() : isInstanceX(type, arg);
}
static void arraycopy(Object[] a, Object[] b) {
if (a != null && b != null)
arraycopy(a, 0, b, 0, Math.min(a.length, b.length));
}
static void arraycopy(Object src, int srcPos, int destPos, int n) { arraycopy(src, srcPos, src, destPos, n); }
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int n) {
if (n != 0)
System.arraycopy(src, srcPos, dest, destPos, n);
}
static A[] arrayOfType(Class type, int n) {
return makeArray(type, n);
}
static A[] arrayOfType(int n, Class type) {
return arrayOfType(type, n);
}
public static String join(String glue, Iterable strings) {
if (strings == null) return "";
if (strings instanceof Collection) {
if (((Collection) strings).size() == 1) return str(first((Collection) strings));
}
StringBuilder buf = new StringBuilder();
Iterator i = strings.iterator();
if (i.hasNext()) {
buf.append(i.next());
while (i.hasNext())
buf.append(glue).append(i.next());
}
return buf.toString();
}
public static String join(String glue, String... strings) {
return join(glue, Arrays.asList(strings));
}
public static String join(String glue, Object... strings) {
return join(glue, Arrays.asList(strings));
}
static String join(Iterable strings) {
return join("", strings);
}
static String join(Iterable strings, String glue) {
return join(glue, strings);
}
public static String join(String[] strings) {
return join("", strings);
}
static String join(String glue, Pair p) {
return p == null ? "" : str(p.a) + glue + str(p.b);
}
static String str(Object o) {
return o == null ? "null" : o.toString();
}
static String str(char[] c) {
return new String(c);
}
static List getClassNames(Collection l) {
List out = new ArrayList();
if (l != null) for (Object o : l)
out.add(o == null ? null : getClassName(o));
return out;
}
static AutoCloseable tempInterceptPrintIfNotIntercepted(F1 f) {
return print_byThread().get() == null ? tempInterceptPrint(f) : null;
}
static Class __javax;
static Class getJavaX() { try {
return __javax;
} catch (Exception __e) { throw rethrow(__e); } }
static void __setJavaX(Class j) {
__javax = j;
_onJavaXSet();
}
static HashMap> callMC_cache = new HashMap();
static String callMC_key;
static Method callMC_value;
// varargs assignment fixer for a single string array argument
static Object callMC(String method, String[] arg) {
return callMC(method, new Object[] {arg});
}
static Object callMC(String method, Object... args) { try {
Method me;
if (callMC_cache == null) callMC_cache = new HashMap(); // initializer time workaround
synchronized(callMC_cache) {
me = method == callMC_key ? callMC_value : null;
}
if (me != null) try {
return invokeMethod(me, null, args);
} catch (IllegalArgumentException e) {
throw new RuntimeException("Can't call " + me + " with arguments " + classNames(args), e);
}
List m;
synchronized(callMC_cache) {
m = callMC_cache.get(method);
}
if (m == null) {
if (callMC_cache.isEmpty()) {
callMC_makeCache();
m = callMC_cache.get(method);
}
if (m == null) throw fail("Method named " + method + " not found in main");
}
int n = m.size();
if (n == 1) {
me = m.get(0);
synchronized(callMC_cache) {
callMC_key = method;
callMC_value = me;
}
try {
return invokeMethod(me, null, args);
} catch (IllegalArgumentException e) {
throw new RuntimeException("Can't call " + me + " with arguments " + classNames(args), e);
}
}
for (int i = 0; i < n; i++) {
me = m.get(i);
if (call_checkArgs(me, args, false))
return invokeMethod(me, null, args);
}
throw fail("No method called " + method + " with arguments (" + joinWithComma(getClasses(args)) + ") found in main");
} catch (Exception __e) { throw rethrow(__e); } }
static void callMC_makeCache() {
synchronized(callMC_cache) {
callMC_cache.clear();
Class _c = (Class) mc(), c = _c;
while (c != null) {
for (Method m : c.getDeclaredMethods())
if ((m.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) {
makeAccessible(m);
multiMapPut(callMC_cache, m.getName(), m);
}
c = c.getSuperclass();
}
}
}
static List synchroList() {
return synchroList(new ArrayList ());
}
static List synchroList(List l) {
return Collections.synchronizedList(l);
}
static Pair pair(A a, B b) {
return new Pair(a, b);
}
static Pair pair(A a) {
return new Pair(a, a);
}
static A assertNotNull(A a) {
assertTrue(a != null);
return a;
}
static A assertNotNull(String msg, A a) {
assertTrue(msg, a != null);
return a;
}
static Map synchroHashMap() {
return synchronizedMap(new HashMap());
}
static String combinePrintParameters(String s, Object o) {
return (endsWithLetterOrDigit(s) ? s + ": " : s) + o;
}
static void ping_okInCleanUp() {
if (ping_pauseAll || ping_anyActions)
ping_impl(true);
}
// this syntax should be removed...
static Object getThreadLocal(Object o, String name) {
ThreadLocal t = (ThreadLocal) (getOpt(o, name));
return t != null ? t.get() : null;
}
static A getThreadLocal(ThreadLocal tl) {
return tl == null ? null : tl.get();
}
static A getThreadLocal(ThreadLocal tl, A defaultValue) {
return or(getThreadLocal(tl), defaultValue);
}
static ThreadLocal print_byThread_dontCreate() {
return print_byThread;
}
static boolean isFalse(Object o) {
return eq(false, o);
}
static String getStackTrace(Throwable throwable) {
lastException(throwable);
return getStackTrace_noRecord(throwable);
}
static String getStackTrace_noRecord(Throwable throwable) {
StringWriter writer = new StringWriter();
throwable.printStackTrace(new PrintWriter(writer));
return hideCredentials(writer.toString());
}
static String getStackTrace() {
return getStackTrace_noRecord(new Throwable());
}
static String getStackTrace(String msg) {
return getStackTrace_noRecord(new Throwable(msg));
}
static String fixNewLines(String s) {
int i = indexOf(s, '\r');
if (i < 0) return s;
int l = s.length();
StringBuilder out = new StringBuilder(l);
out.append(s, 0, i);
for (; i < l; i++) {
char c = s.charAt(i);
if (c != '\r')
out.append(c);
else {
out.append('\n');
if (i+1 < l && s.charAt(i+1) == '\n') ++i;
}
}
return out.toString();
}
static void print_append(Appendable buf, String s, int max) { try {
synchronized(buf) {
buf.append(s);
if (buf instanceof StringBuffer)
rotateStringBuffer(((StringBuffer) buf), max);
else if (buf instanceof StringBuilder)
rotateStringBuilder(((StringBuilder) buf), max);
}
} catch (Exception __e) { throw rethrow(__e); } }
static Class mc() {
return main.class;
}
static Object vmBus_wrapArgs(Object... args) {
return empty(args) ? null
: l(args) == 1 ? args[0]
: args;
}
static void pcallFAll_minimalExceptionHandling(Collection l, Object... args) {
if (l != null) for (Object f : cloneList(l)) { ping(); pcallF_minimalExceptionHandling(f, args); }
}
static void pcallFAll_minimalExceptionHandling(Iterator it, Object... args) {
while (it.hasNext()) { ping(); pcallF_minimalExceptionHandling(it.next(), args); }
}
static Set vm_busListeners_live_cache;
static Set vm_busListeners_live() { if (vm_busListeners_live_cache == null) vm_busListeners_live_cache = vm_busListeners_live_load(); return vm_busListeners_live_cache; }
static Set vm_busListeners_live_load() {
return vm_generalIdentityHashSet("busListeners");
}
static Map vm_busListenersByMessage_live_cache;
static Map vm_busListenersByMessage_live() { if (vm_busListenersByMessage_live_cache == null) vm_busListenersByMessage_live_cache = vm_busListenersByMessage_live_load(); return vm_busListenersByMessage_live_cache; }
static Map vm_busListenersByMessage_live_load() {
return vm_generalHashMap("busListenersByMessage");
}
static A[] makeArray(Class type, int n) {
return (A[]) Array.newInstance(type, n);
}
static Object first(Object list) {
return first((Iterable) list);
}
static A first(List list) {
return empty(list) ? null : list.get(0);
}
static A first(A[] bla) {
return bla == null || bla.length == 0 ? null : bla[0];
}
static Pair first(Map map) {
return mapEntryToPair(first(entrySet(map)));
}
static Pair first(MultiMap mm) {
if (mm == null) return null;
var e = first(mm.data.entrySet());
if (e == null) return null;
return pair(e.getKey(), first(e.getValue()));
}
static A first(IterableIterator i) {
return first((Iterator ) i);
}
static A first(Iterator i) {
return i == null || !i.hasNext() ? null : i.next();
}
static A first(Iterable i) {
if (i == null) return null;
Iterator it = i.iterator();
return it.hasNext() ? it.next() : null;
}
static Character first(String s) { return empty(s) ? null : s.charAt(0); }
static Character first(CharSequence s) { return empty(s) ? null : s.charAt(0); }
static A first(Pair p) {
return p == null ? null : p.a;
}
static A first(T3 t) {
return t == null ? null : t.a;
}
static Byte first(byte[] l) {
return empty(l) ? null : l[0];
}
static int first(IntBuffer buf) {
return buf.get(0);
}
static A first(A[] l, IF1 pred) {
return firstThat(l, pred);
}
static A first(Iterable l, IF1 pred) {
return firstThat(l, pred);
}
static A first(IF1 pred, Iterable l) {
return firstThat(pred, l);
}
static A first(AppendableChain a) {
return a == null ? null : a.element;
}
static ThreadLocal print_byThread() {
synchronized(print_byThread_lock) {
if (print_byThread == null)
print_byThread = new ThreadLocal();
}
return print_byThread;
}
// f can return false to suppress regular printing
// call print_raw within f to actually print something
static AutoCloseable tempInterceptPrint(F1 f) {
return tempSetThreadLocal(print_byThread(), f);
}
static void _onJavaXSet() {}
static List getClasses(Object[] array) {
List l = emptyList(l(array));
for (Object o : array) l.add(_getClass(o));
return l;
}
static void multiMapPut(Map > map, A a, B b) {
List l = map.get(a);
if (l == null)
map.put(a, l = new ArrayList());
l.add(b);
}
static void multiMapPut(MultiMap mm, A key, B value) {
if (mm != null && key != null && value != null) mm.put(key, value);
}
static void assertTrue(Object o) {
if (!(eq(o, true) /*|| isTrue(pcallF(o))*/))
throw fail(str(o));
}
static boolean assertTrue(String msg, boolean b) {
if (!b)
throw fail(msg);
return b;
}
static boolean assertTrue(boolean b) {
if (!b)
throw fail("oops");
return b;
}
static Map synchronizedMap() {
return synchroMap();
}
static Map synchronizedMap(Map map) {
return synchroMap(map);
}
static boolean endsWithLetterOrDigit(String s) {
return s != null && s.length() > 0 && Character.isLetterOrDigit(s.charAt(s.length()-1));
}
//sbool ping_actions_shareable = true;
static volatile boolean ping_pauseAll = false;
static int ping_sleep = 100; // poll pauseAll flag every 100
static volatile boolean ping_anyActions = false;
static Map ping_actions = newWeakHashMap();
static ThreadLocal ping_isCleanUpThread = new ThreadLocal();
// always returns true
static boolean ping() {
//ifdef useNewPing
newPing();
//endifdef
if (ping_pauseAll || ping_anyActions) ping_impl(true /* XXX */);
//ifndef LeanMode ping_impl(); endifndef
return true;
}
// returns true when it slept
static boolean ping_impl(boolean okInCleanUp) { try {
if (ping_pauseAll && !isAWTThread()) {
do
Thread.sleep(ping_sleep);
while (ping_pauseAll);
return true;
}
if (ping_anyActions) { // don't allow sharing ping_actions
if (!okInCleanUp && !isTrue(ping_isCleanUpThread.get()))
failIfUnlicensed();
Object action = null;
synchronized(ping_actions) {
if (!ping_actions.isEmpty()) {
action = ping_actions.get(currentThread());
if (action instanceof Runnable)
ping_actions.remove(currentThread());
if (ping_actions.isEmpty()) ping_anyActions = false;
}
}
if (action instanceof Runnable)
((Runnable) action).run();
else if (eq(action, "cancelled"))
throw fail("Thread cancelled.");
}
return false;
} catch (Exception __e) { throw rethrow(__e); } }
static Object getOpt(Object o, String field) {
return getOpt_cached(o, field);
}
static Object getOpt(String field, Object o) {
return getOpt_cached(o, field);
}
static Object getOpt_raw(Object o, String field) { try {
Field f = getOpt_findField(o.getClass(), field);
if (f == null) return null;
makeAccessible(f);
return f.get(o);
} catch (Exception __e) { throw rethrow(__e); } }
// access of static fields is not yet optimized
static Object getOpt(Class c, String field) { try {
if (c == null) return null;
Field f = getOpt_findStaticField(c, field);
if (f == null) return null;
makeAccessible(f);
return f.get(null);
} catch (Exception __e) { throw rethrow(__e); } }
static Field getOpt_findStaticField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
return null;
}
static A or(A a, A b) {
return a != null ? a : b;
}
static boolean eq(Object a, Object b) {
return a == b || a != null && b != null && a.equals(b);
}
// a little kludge for stuff like eq(symbol, "$X")
static boolean eq(Symbol a, String b) {
return eq(str(a), b);
}
// PersistableThrowable doesn't hold GC-disturbing class references in backtrace
static volatile PersistableThrowable lastException_lastException;
static PersistableThrowable lastException() {
return lastException_lastException;
}
static void lastException(Throwable e) {
lastException_lastException = persistableThrowable(e);
}
static String hideCredentials(URL url) { return url == null ? null : hideCredentials(str(url)); }
static String hideCredentials(String url) {
try {
if (startsWithOneOf(url, "http://", "https://") && isAGIBlueDomain(hostNameFromURL(url))) return url;
} catch (Throwable e) {
print("HideCredentials", e);
}
return url.replaceAll("([&?])(_pass|key|cookie)=[^&\\s\"]*", "$1$2=");
}
static String hideCredentials(Object o) {
return hideCredentials(str(o));
}
static int indexOf(List l, A a, int startIndex) {
if (l == null) return -1;
int n = l(l);
for (int i = startIndex; i < n; i++)
if (eq(l.get(i), a))
return i;
return -1;
}
static int indexOf(List l, int startIndex, A a) {
return indexOf(l, a, startIndex);
}
static int indexOf(List l, A a) {
if (l == null) return -1;
return l.indexOf(a);
}
static int indexOf(String a, String b) {
return a == null || b == null ? -1 : a.indexOf(b);
}
static int indexOf(String a, String b, int i) {
return a == null || b == null ? -1 : a.indexOf(b, i);
}
static int indexOf(String a, char b) {
return a == null ? -1 : a.indexOf(b);
}
static int indexOf(String a, int i, char b) {
return indexOf(a, b, i);
}
static int indexOf(String a, char b, int i) {
return a == null ? -1 : a.indexOf(b, i);
}
static int indexOf(String a, int i, String b) {
return a == null || b == null ? -1 : a.indexOf(b, i);
}
static int indexOf(A[] x, A a) {
int n = l(x);
for (int i = 0; i < n; i++)
if (eq(x[i], a))
return i;
return -1;
}
static int indexOf(Iterable l, A a) {
if (l == null) return -1;
int i = 0;
for (A x : l) {
if (eq(x, a))
return i;
i++;
}
return -1;
}
static void rotateStringBuffer(StringBuffer buf, int max) { try {
if (buf == null) return;
synchronized(buf) {
if (buf.length() <= max) return;
try {
int newLength = max/2;
int ofs = buf.length()-newLength;
String newString = buf.substring(ofs);
buf.setLength(0);
buf.append("[...] ").append(newString);
} catch (Exception e) {
buf.setLength(0);
}
buf.trimToSize();
}
} catch (Exception __e) { throw rethrow(__e); } }
static void rotateStringBuilder(StringBuilder buf, int max) { try {
if (buf == null) return;
synchronized(buf) {
if (buf.length() <= max) return;
try {
int newLength = max/2;
int ofs = buf.length()-newLength;
String newString = buf.substring(ofs);
buf.setLength(0);
buf.append("[...] ").append(newString);
} catch (Exception e) {
buf.setLength(0);
}
buf.trimToSize();
}
} catch (Exception __e) { throw rethrow(__e); } }
static ArrayList cloneList(Iterable l) {
return l instanceof Collection ? cloneList((Collection) l) : asList(l);
}
static ArrayList cloneList(Collection l) {
if (l == null) return new ArrayList();
synchronized(collectionMutex(l)) {
return new ArrayList (l);
}
}
static Object pcallF_minimalExceptionHandling(Object f, Object... args) {
try {
return callFunction(f, args);
} catch (Throwable e) {
System.out.println(getStackTrace(e));
_storeException(e);
}
return null;
}
static Set vm_generalIdentityHashSet(Object name) {
synchronized(vm_generalMap()) {
Set set = (Set) (vm_generalMap_get(name));
if (set == null)
vm_generalMap_put(name, set = syncIdentityHashSet());
return set;
}
}
static Map vm_generalHashMap(Object name) {
synchronized(vm_generalMap()) {
Map m = (Map) (vm_generalMap_get(name));
if (m == null)
vm_generalMap_put(name, m = syncHashMap());
return m;
}
}
static Pair mapEntryToPair(Map.Entry e) {
return e == null ? null : pair(e.getKey(), e.getValue());
}
static Set> entrySet(Map map) {
return _entrySet(map);
}
static A firstThat(Iterable l, IF1 pred) {
for (A a : unnullForIteration(l))
if (pred.get(a))
return a;
return null;
}
static A firstThat(A[] l, IF1 pred) {
for (A a : unnullForIteration(l))
if (pred.get(a))
return a;
return null;
}
static A firstThat(IF1 pred, Iterable l) {
return firstThat(l, pred);
}
static A firstThat(IF1 pred, A[] l) {
return firstThat(l, pred);
}
static AutoCloseable tempSetThreadLocal(final ThreadLocal tl, A a) {
if (tl == null) return null;
final A prev = setThreadLocal(tl, a);
return new AutoCloseable() { public String toString() { return "tl.set(prev);"; } public void close() throws Exception { tl.set(prev); }};
}
static ArrayList emptyList() {
return new ArrayList();
//ret Collections.emptyList();
}
static ArrayList emptyList(int capacity) {
return new ArrayList(max(0, capacity));
}
// Try to match capacity
static ArrayList emptyList(Iterable l) {
return l instanceof Collection ? emptyList(((Collection) l).size()) : emptyList();
}
static ArrayList emptyList(Object[] l) {
return emptyList(l(l));
}
// get correct type at once
static ArrayList emptyList(Class c) {
return new ArrayList();
}
static Class> _getClass(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException e) {
return null; // could optimize this
}
}
static Class _getClass(Object o) {
return o == null ? null
: o instanceof Class ? (Class) o : o.getClass();
}
static Class _getClass(Object realm, String name) {
try {
return classLoaderForObject(realm).loadClass(classNameToVM(name));
} catch (ClassNotFoundException e) {
return null; // could optimize this
}
}
static Map newWeakHashMap() {
return _registerWeakMap(synchroMap(new WeakHashMap()));
}
static void newPing() {
var tl = newPing_actionTL();
Runnable action = tl == null ? null : tl.get();
{ if (action != null) action.run(); }
}
// TODO: test if android complains about this
static boolean isAWTThread() {
if (isAndroid()) return false;
if (isHeadless()) return false;
return isAWTThread_awt();
}
static boolean isAWTThread_awt() {
return SwingUtilities.isEventDispatchThread();
}
static boolean isTrue(Object o) {
if (o instanceof Boolean)
return ((Boolean) o).booleanValue();
if (o == null) return false;
if (o instanceof ThreadLocal) // TODO: remove this
return isTrue(((ThreadLocal) o).get());
throw fail(getClassName(o));
}
static boolean isTrue(Boolean b) {
return b != null && b.booleanValue();
}
static void failIfUnlicensed() {
assertTrue("license off", licensed());
}
static Thread currentThread() {
return Thread.currentThread();
}
//static final Map> getOpt_cache = newDangerousWeakHashMap(f getOpt_special_init);
static class getOpt_Map extends WeakHashMap {
getOpt_Map() {
if (getOpt_special == null) getOpt_special = new HashMap();
clear();
}
public void clear() {
super.clear();
//print("getOpt clear");
put(Class.class, getOpt_special);
put(String.class, getOpt_special);
}
}
static final Map> getOpt_cache = _registerDangerousWeakMap(synchroMap(new getOpt_Map()));
//static final Map> getOpt_cache = _registerWeakMap(synchroMap(new getOpt_Map));
static HashMap getOpt_special; // just a marker
/*static void getOpt_special_init(Map map) {
map.put(Class.class, getOpt_special);
map.put(S.class, getOpt_special);
}*/
static Map getOpt_getFieldMap(Object o) {
Class c = _getClass(o);
HashMap map = getOpt_cache.get(c);
if (map == null)
map = getOpt_makeCache(c);
return map;
}
static Object getOpt_cached(Object o, String field) { try {
if (o == null) return null;
Map map = getOpt_getFieldMap(o);
if (map == getOpt_special) {
if (o instanceof Class)
return getOpt((Class) o, field);
/*if (o instanceof S)
ret getOpt(getBot((S) o), field);*/
if (o instanceof Map)
return ((Map) o).get(field);
}
Field f = map.get(field);
if (f != null) return f.get(o);
if (o instanceof DynamicObject)
return syncMapGet2(((DynamicObject) o).fieldValues, field);
return null;
} catch (Exception __e) { throw rethrow(__e); } }
// used internally - we are in synchronized block
static HashMap getOpt_makeCache(Class c) {
HashMap map;
if (isSubtypeOf(c, Map.class))
map = getOpt_special;
else {
map = new HashMap();
if (!reflection_classesNotToScan().contains(c.getName())) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields()) {
makeAccessible(f);
String name = f.getName();
if (!map.containsKey(name))
map.put(name, f);
}
_c = _c.getSuperclass();
} while (_c != null);
}
}
if (getOpt_cache != null) getOpt_cache.put(c, map);
return map;
}
static Field getOpt_findField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field))
return f;
_c = _c.getSuperclass();
} while (_c != null);
return null;
}
static PersistableThrowable persistableThrowable(Throwable e) {
return e == null ? null : new PersistableThrowable(e);
}
static boolean startsWithOneOf(String s, String... l) {
for (String x : l) if (startsWith(s, x)) return true; return false;
}
static boolean startsWithOneOf(String s, Matches m, String... l) {
for (String x : l) if (startsWith(s, x, m)) return true; return false;
}
static boolean isAGIBlueDomain(String domain) {
return domainIsUnder(domain, theAGIBlueDomain());
}
static String hostNameFromURL(String url) { try {
return empty(url) ? null : new URL(url).getHost();
} catch (Exception __e) { throw rethrow(__e); } }
// unclear semantics as to whether return null on null
static ArrayList asList(A[] a) {
return a == null ? new ArrayList () : new ArrayList (Arrays.asList(a));
}
static ArrayList asList(int[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (int i : a) l.add(i);
return l;
}
static ArrayList asList(long[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (long i : a) l.add(i);
return l;
}
static ArrayList asList(float[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (float i : a) l.add(i);
return l;
}
static ArrayList asList(double[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (double i : a) l.add(i);
return l;
}
static ArrayList asList(short[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (short i : a) l.add(i);
return l;
}
static ArrayList asList(Iterator it) {
ArrayList l = new ArrayList();
if (it != null)
while (it.hasNext())
l.add(it.next());
return l;
}
// disambiguation
static ArrayList asList(IterableIterator s) {
return asList((Iterator) s);
}
static ArrayList asList(Iterable s) {
if (s instanceof ArrayList) return (ArrayList) s;
ArrayList l = new ArrayList();
if (s != null)
for (A a : s)
l.add(a);
return l;
}
static ArrayList asList(Producer p) {
ArrayList l = new ArrayList();
A a;
if (p != null) while ((a = p.next()) != null)
l.add(a);
return l;
}
static ArrayList asList(Enumeration e) {
ArrayList l = new ArrayList();
if (e != null)
while (e.hasMoreElements())
l.add(e.nextElement());
return l;
}
static ArrayList asList(ReverseChain c) {
return c == null ? emptyList() : c.toList();
}
static List asList(Pair p) {
return p == null ? null : ll(p.a, p.b);
}
// TODO: JDK 17!! ?? No! Yes? Yes!!
static Object collectionMutex(List l) {
return l;
}
static Object collectionMutex(Object o) {
if (o instanceof List) return o;
// TODO: actually use our own maps so we can get the mutex properly
String c = className(o);
return o;
}
static Object callFunction(Object f, Object... args) {
return callF(f, args);
}
static Throwable _storeException_value;
static void _storeException(Throwable e) {
_storeException_value = e;
}
static Map vm_generalMap_map;
static Map vm_generalMap() {
if (vm_generalMap_map == null)
vm_generalMap_map = (Map) get(javax(), "generalMap");
return vm_generalMap_map;
}
static Object vm_generalMap_get(Object key) {
return vm_generalMap().get(key);
}
static Object vm_generalMap_put(Object key, Object value) {
return mapPutOrRemove(vm_generalMap(), key, value);
}
static Set syncIdentityHashSet() {
return (Set) synchronizedSet(identityHashSet());
}
static Map syncHashMap() {
return synchroHashMap();
}
static Set> _entrySet(Map map) {
return map == null ? Collections.EMPTY_SET : map.entrySet();
}
static String unnullForIteration(String s) {
return s == null ? "" : s;
}
static Collection unnullForIteration(Collection l) {
return l == null ? immutableEmptyList() : l;
}
static List unnullForIteration(List l) { return l == null ? immutableEmptyList() : l; }
static int[] unnullForIteration(int[] l) { return l == null ? emptyIntArray() : l; }
static char[] unnullForIteration(char[] l) { return l == null ? emptyCharArray() : l; }
static double[] unnullForIteration(double[] l) { return l == null ? emptyDoubleArray() : l; }
static short[] unnullForIteration(short[] l) { return l == null ? emptyShortArray() : l; }
static Map unnullForIteration(Map l) {
return l == null ? immutableEmptyMap() : l;
}
static Iterable unnullForIteration(Iterable i) {
return i == null ? immutableEmptyList() : i;
}
static A[] unnullForIteration(A[] a) {
return a == null ? (A[]) emptyObjectArray() : a;
}
static BitSet unnullForIteration(BitSet b) {
return b == null ? new BitSet() : b;
}
static Pt unnullForIteration(Pt p) {
return p == null ? new Pt() : p;
}
//ifclass Symbol
static Symbol unnullForIteration(Symbol s) {
return s == null ? emptySymbol() : s;
}
//endif
static Pair unnullForIteration(Pair p) {
return p != null ? p : new Pair(null, null);
}
static long unnullForIteration(Long l) { return l == null ? 0L : l; }
static A setThreadLocal(ThreadLocal tl, A value) {
if (tl == null) return null;
A old = tl.get();
tl.set(value);
return old;
}
static int max(int a, int b) { return Math.max(a, b); }
static int max(int a, int b, int c) { return max(max(a, b), c); }
static long max(int a, long b) { return Math.max((long) a, b); }
static long max(long a, long b) { return Math.max(a, b); }
static double max(int a, double b) { return Math.max((double) a, b); }
static float max(float a, float b) { return Math.max(a, b); }
static double max(double a, double b) { return Math.max(a, b); }
static int max(Collection c) {
int x = Integer.MIN_VALUE;
for (int i : c) x = max(x, i);
return x;
}
static double max(double[] c) {
if (c.length == 0) return Double.MIN_VALUE;
double x = c[0];
for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]);
return x;
}
static float max(float[] c) {
if (c.length == 0) return Float.MAX_VALUE;
float x = c[0];
for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]);
return x;
}
static byte max(byte[] c) {
byte x = -128;
for (byte d : c) if (d > x) x = d;
return x;
}
static short max(short[] c) {
short x = -0x8000;
for (short d : c) if (d > x) x = d;
return x;
}
static int max(int[] c) {
int x = Integer.MIN_VALUE;
for (int d : c) if (d > x) x = d;
return x;
}
static > A max(A a, A b) {
return cmp(a, b) >= 0 ? a : b;
}
static ClassLoader classLoaderForObject(Object o) {
if (o instanceof ClassLoader) return ((ClassLoader) o);
if (o == null) return null;
return _getClass(o).getClassLoader();
}
// Note: This is actually broken. Inner classes must stay with a $ separator
static String classNameToVM(String name) {
return name.replace(".", "$");
}
static List _registerWeakMap_preList;
static A _registerWeakMap(A map) {
if (javax() == null) {
// We're in class init
if (_registerWeakMap_preList == null) _registerWeakMap_preList = synchroList();
_registerWeakMap_preList.add(map);
return map;
}
try {
call(javax(), "_registerWeakMap", map);
} catch (Throwable e) {
printException(e);
print("Upgrade JavaX!!");
}
return map;
}
static void _onLoad_registerWeakMap() {
assertNotNull(javax());
if (_registerWeakMap_preList == null) return;
for (Object o : _registerWeakMap_preList)
_registerWeakMap(o);
_registerWeakMap_preList = null;
}
static x30_pkg.x30_util.BetterThreadLocal newPing_actionTL;
static x30_pkg.x30_util.BetterThreadLocal newPing_actionTL() {
if (newPing_actionTL == null)
newPing_actionTL = vm_generalMap_getOrCreate("newPing_actionTL",
() -> {
Runnable value = (Runnable) (callF_gen(vm_generalMap_get("newPing_valueForNewThread")));
var tl = new x30_pkg.x30_util.BetterThreadLocal();
tl.set(value);
return tl;
});
return newPing_actionTL;
}
static int isAndroid_flag;
static boolean isAndroid() {
if (isAndroid_flag == 0)
isAndroid_flag = System.getProperty("java.vendor").toLowerCase().indexOf("android") >= 0 ? 1 : -1;
return isAndroid_flag > 0;
}
static Boolean isHeadless_cache;
static boolean isHeadless() {
if (isHeadless_cache != null) return isHeadless_cache;
if (isAndroid()) return isHeadless_cache = true;
if (GraphicsEnvironment.isHeadless()) return isHeadless_cache = true;
// Also check if AWT actually works.
// If DISPLAY variable is set but no X server up, this will notice.
try {
SwingUtilities.isEventDispatchThread();
return isHeadless_cache = false;
} catch (Throwable e) { return isHeadless_cache = true; }
}
static volatile boolean licensed_yes = true;
static boolean licensed() {
if (!licensed_yes) return false;
ping_okInCleanUp();
return true;
}
static void licensed_off() {
licensed_yes = false;
}
static void clear(Collection c) {
if (c != null) c.clear();
}
static void clear(Map map) {
if (map != null) map.clear();
}
static void put(Map map, A a, B b) {
if (map != null) map.put(a, b);
}
static void put(List l, int i, A a) {
if (l != null && i >= 0 && i < l(l)) l.set(i, a);
}
static B syncMapGet2(Map map, A a) {
if (map == null) return null;
synchronized(collectionMutex(map)) {
return map.get(a);
}
}
static B syncMapGet2(A a, Map map) {
return syncMapGet2(map, a);
}
static boolean isSubtypeOf(Class a, Class b) {
return a != null && b != null && b.isAssignableFrom(a); // << always hated that method, let's replace it!
}
static Set reflection_classesNotToScan_value = litset(
"jdk.internal.loader.URLClassPath"
);
static Set reflection_classesNotToScan() {
return reflection_classesNotToScan_value;
}
static boolean startsWith(String a, String b) {
return a != null && a.startsWith(unnull(b));
}
static boolean startsWith(String a, char c) {
return nemptyString(a) && a.charAt(0) == c;
}
static boolean startsWith(String a, String b, Matches m) {
if (!startsWith(a, b)) return false;
if (m != null) m.m = new String[] {substring(a, strL(b))};
return true;
}
static boolean startsWith(List a, List b) {
if (a == null || listL(b) > listL(a)) return false;
for (int i = 0; i < listL(b); i++)
if (neq(a.get(i), b.get(i)))
return false;
return true;
}
static boolean domainIsUnder(String domain, String mainDomain) {
return eqic(domain, mainDomain) || ewic(domain, "." + mainDomain);
}
static String theAGIBlueDomain() {
return "agi.blue";
}
static List ll(A... a) {
ArrayList l = new ArrayList(a.length);
if (a != null) for (A x : a) l.add(x);
return l;
}
static String className(Object o) {
return getClassName(o);
}
// get purpose 1: access a list/array/map (safer version of x.get(y))
static A get(List l, int idx) {
return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null;
}
// seems to conflict with other signatures
/*static B get(Map map, A key) {
ret map != null ? map.get(key) : null;
}*/
static A get(A[] l, int idx) {
return idx >= 0 && idx < l(l) ? l[idx] : null;
}
// default to false
static boolean get(boolean[] l, int idx) {
return idx >= 0 && idx < l(l) ? l[idx] : false;
}
// get purpose 2: access a field by reflection or a map
static Object get(Object o, String field) {
try {
if (o == null) return null;
if (o instanceof Class) return get((Class) o, field);
if (o instanceof Map)
return ((Map) o).get(field);
Field f = getOpt_findField(o.getClass(), field);
if (f != null) {
makeAccessible(f);
return f.get(o);
}
if (o instanceof DynamicObject)
return getOptDynOnly(((DynamicObject) o), field);
} catch (Exception e) {
throw asRuntimeException(e);
}
throw new RuntimeException("Field '" + field + "' not found in " + o.getClass().getName());
}
static Object get_raw(String field, Object o) {
return get_raw(o, field);
}
static Object get_raw(Object o, String field) { try {
if (o == null) return null;
Field f = get_findField(o.getClass(), field);
makeAccessible(f);
return f.get(o);
} catch (Exception __e) { throw rethrow(__e); } }
static Object get(Class c, String field) {
try {
Field f = get_findStaticField(c, field);
makeAccessible(f);
return f.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Field get_findStaticField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
throw new RuntimeException("Static field '" + field + "' not found in " + c.getName());
}
static Field get_findField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field))
return f;
_c = _c.getSuperclass();
} while (_c != null);
throw new RuntimeException("Field '" + field + "' not found in " + c.getName());
}
static Object get(String field, Object o) {
return get(o, field);
}
static boolean get(BitSet bs, int idx) {
return bs != null && bs.get(idx);
}
static B mapPutOrRemove(Map map, A key, B value) {
if (map != null && key != null)
if (value != null) return map.put(key, value);
else return map.remove(key);
return null;
}
static Set synchronizedSet() {
return synchroHashSet();
}
static Set synchronizedSet(Set set) {
return Collections.synchronizedSet(set);
}
static Set identityHashSet() {
return Collections.newSetFromMap(new IdentityHashMap());
}
static List immutableEmptyList() {
return Collections.emptyList();
}
static int[] emptyIntArray_a = new int[0];
static int[] emptyIntArray() { return emptyIntArray_a; }
static char[] emptyCharArray = new char[0];
static char[] emptyCharArray() { return emptyCharArray; }
static double[] emptyDoubleArray = new double[0];
static double[] emptyDoubleArray() { return emptyDoubleArray; }
static short[] emptyShortArray = new short[0];
static short[] emptyShortArray() { return emptyShortArray; }
static Map immutableEmptyMap() {
return Collections.emptyMap();
}
static Object[] emptyObjectArray_a = new Object[0];
static Object[] emptyObjectArray() { return emptyObjectArray_a; }
static Symbol emptySymbol_value;
static Symbol emptySymbol() {
if (emptySymbol_value == null) emptySymbol_value = symbol("");
return emptySymbol_value;
}
static A printException(A e) {
printStackTrace(e);
return e;
}
static A vm_generalMap_getOrCreate(Object key, F0 create) {
return vm_generalMap_getOrCreate(key, f0ToIF0(create));
}
static A vm_generalMap_getOrCreate(Object key, IF0 create) {
Map generalMap = vm_generalMap();
if (generalMap == null) return null; // must be x30 init
synchronized(generalMap) { // should switch to locks here
A a = (A) (vm_generalMap_get(key));
if (a == null)
vm_generalMap_put(key, a = create == null ? null : create.get());
return a;
}
}
static A callF_gen(F0 f) {
return f == null ? null : f.get();
}
static B callF_gen(F1 f, A a) {
return f == null ? null : f.get(a);
}
static A callF_gen(IF0 f) {
return f == null ? null : f.get();
}
static B callF_gen(IF1 f, A a) {
return f == null ? null : f.get(a);
}
static B callF_gen(A a, IF1 f) {
return f == null ? null : f.get(a);
}
static C callF_gen(IF2 f, A a, B b) {
return f == null ? null : f.get(a, b);
}
static void callF_gen(VF1 f, A a) {
{ if (f != null) f.get(a); }
}
static void callF_gen(A a, IVF1 f) {
{ if (f != null) f.get(a); }
}
static void callF_gen(IVF1 f, A a) {
{ if (f != null) f.get(a); }
}
static Object callF_gen(Runnable r) { { if (r != null) r.run(); } return null; }
static Object callF_gen(Object f, Object... args) {
return callF(f, args);
}
static HashSet litset(A... items) {
return lithashset(items);
}
static String unnull(String s) {
return s == null ? "" : s;
}
static Collection unnull(Collection l) {
return l == null ? emptyList() : l;
}
static List unnull(List l) { return l == null ? emptyList() : l; }
static int[] unnull(int[] l) { return l == null ? emptyIntArray() : l; }
static char[] unnull(char[] l) { return l == null ? emptyCharArray() : l; }
static double[] unnull(double[] l) { return l == null ? emptyDoubleArray() : l; }
static Map unnull(Map l) {
return l == null ? emptyMap() : l;
}
static Iterable unnull(Iterable i) {
return i == null ? emptyList() : i;
}
static A[] unnull(A[] a) {
return a == null ? (A[]) emptyObjectArray() : a;
}
static BitSet unnull(BitSet b) {
return b == null ? new BitSet() : b;
}
static Pt unnull(Pt p) {
return p == null ? new Pt() : p;
}
//ifclass Symbol
static Symbol unnull(Symbol s) {
return s == null ? emptySymbol() : s;
}
//endif
static Pair unnull(Pair p) {
return p != null ? p : new Pair(null, null);
}
static int unnull(Integer i) { return i == null ? 0 : i; }
static long unnull(Long l) { return l == null ? 0L : l; }
static double unnull(Double l) { return l == null ? 0.0 : l; }
static boolean nemptyString(String s) {
return s != null && s.length() > 0;
}
static String substring(String s, int x) {
return substring(s, x, strL(s));
}
static String substring(String s, int x, int y) {
if (s == null) return null;
if (x < 0) x = 0;
int n = s.length();
if (y < x) y = x;
if (y > n) y = n;
if (x >= y) return "";
return s.substring(x, y);
}
static String substring(String s, IntRange r) {
return r == null ? null : substring(s, r.start, r.end);
}
// convenience method for quickly dropping a prefix
static String substring(String s, CharSequence l) {
return substring(s, lCharSequence(l));
}
static int strL(String s) {
return s == null ? 0 : s.length();
}
static int listL(Collection l) {
return l == null ? 0 : l.size();
}
static boolean neq(Object a, Object b) {
return !eq(a, b);
}
static boolean eqic(String a, String b) {
if ((a == null) != (b == null)) return false;
if (a == null) return true;
return a.equalsIgnoreCase(b);
}
static boolean eqic(Symbol a, Symbol b) {
return eq(a, b);
}
static boolean eqic(Symbol a, String b) {
return eqic(asString(a), b);
}
static boolean eqic(char a, char b) {
if (a == b) return true;
char u1 = Character.toUpperCase(a);
char u2 = Character.toUpperCase(b);
if (u1 == u2) return true;
return Character.toLowerCase(u1) == Character.toLowerCase(u2);
}
static boolean ewic(String a, String b) {
return endsWithIgnoreCase(a, b);
}
static boolean ewic(String a, String b, Matches m) {
return endsWithIgnoreCase(a, b, m);
}
static Object getOptDynOnly(DynamicObject o, String field) {
if (o == null || o.fieldValues == null) return null;
return o.fieldValues.get(field);
}
static Set synchroHashSet() {
return synchronizedSet(new HashSet ());
}
static WeakHasherMap symbol_map = new WeakHasherMap(new Hasher() {
public int hashCode(Symbol symbol) { return symbol.text.hashCode(); }
public boolean equals(Symbol a, Symbol b) {
if (a == null) return b == null;
return b != null && eq(a.text, b.text);
}
});
static Symbol symbol(String s) {
if (s == null) return null;
synchronized(symbol_map) {
// TODO: avoid object creation by passing the string to findKey
Symbol symbol = new Symbol(s, true);
Symbol existingSymbol = symbol_map.findKey(symbol);
if (existingSymbol == null)
symbol_map.put(existingSymbol = symbol, true);
return existingSymbol;
}
}
static Symbol symbol(CharSequence s) {
if (s == null) return null;
if (s instanceof Symbol) return (Symbol) s;
if (s instanceof String) return symbol((String) s);
return symbol(str(s));
}
static Symbol symbol(Object o) {
return symbol((CharSequence) o);
}
static A printStackTrace(A e) {
// we go to system.out now - system.err is nonsense
if (e != null) print(getStackTrace(e));
return e;
}
static void printStackTrace() {
printStackTrace(new Throwable());
}
static void printStackTrace(String msg) {
printStackTrace(new Throwable(msg));
}
static void printStackTrace(String msg, Throwable e) {
printStackTrace(new Throwable(msg, e));
}
static IF0 f0ToIF0(F0 f) {
return f == null ? null : () -> f.get();
}
static HashSet lithashset(A... items) {
HashSet set = new HashSet();
for (A a : items) set.add(a);
return set;
}
static Map emptyMap() {
return new HashMap();
}
static int lCharSequence(CharSequence s) {
return s == null ? 0 : s.length();
}
static String asString(Object o) {
return o == null ? null : o.toString();
}
static boolean endsWithIgnoreCase(String a, String b) {
int la = l(a), lb = l(b);
return la >= lb && regionMatchesIC(a, la-lb, b, 0, lb);
}
static boolean endsWithIgnoreCase(String a, String b, Matches m) {
if (!endsWithIgnoreCase(a, b)) return false;
if (m != null)
m.m = new String[] { substring(a, 0, l(a)-l(b)) };
return true;
}
static boolean regionMatchesIC(String a, int offsetA, String b, int offsetB, int len) {
return a != null && a.regionMatches(true, offsetA, b, offsetB, len);
}
// immutable, has strong refs
// Do not run in a synchronized block - it goes wrong in the presence
// of elaborate classloaders (like in Gazelle BEA)
// see #1102990 and #1102991
final static class _MethodCache {
final Class c;
final HashMap> cache = new HashMap();
_MethodCache(Class c) {
this.c = c; _init(); }
void _init() {
Class _c = c;
Module myModule = getClass().getModule();
boolean anyHiddenClasses = false;
while (_c != null) {
boolean exported = classIsExportedTo(_c, myModule);
if (!exported)
anyHiddenClasses = true;
else
for (Method m : _c.getDeclaredMethods())
if ((anyHiddenClasses || !isAbstract(m))
&& !reflection_isForbiddenMethod(m))
multiMapPut(cache, m.getName(), makeAccessible(m));
_c = _c.getSuperclass();
}
// add default methods - this might lead to a duplication
// because the overridden method is also added, but it's not
// a problem except for minimal performance loss.
// If any classes in the hierarchy were inaccessible, we add
// all interface methods (see test_callForbiddenMethodByReflection for a test)
for (Class intf : allInterfacesImplementedBy(c))
for (Method m : intf.getDeclaredMethods())
if ((anyHiddenClasses || m.isDefault()) && !reflection_isForbiddenMethod(m))
multiMapPut(cache, m.getName(), makeAccessible(m));
}
// Returns only matching methods
Method findMethod(String method, Object[] args) { try {
List m = cache.get(method);
if (m == null) return null;
int n = m.size();
for (int i = 0; i < n; i++) {
Method me = m.get(i);
if (call_checkArgs(me, args, false))
return me;
}
return null;
} catch (Exception __e) { throw rethrow(__e); } }
Method findStaticMethod(String method, Object[] args) { try {
List m = cache.get(method);
if (m == null) return null;
int n = m.size();
for (int i = 0; i < n; i++) {
Method me = m.get(i);
if (isStaticMethod(me) && call_checkArgs(me, args, false))
return me;
}
return null;
} catch (Exception __e) { throw rethrow(__e); } }
}
static abstract class VF1 implements IVF1 {
public abstract void get(A a);
}
static class Matches {
String[] m;
Matches() {}
Matches(String... m) {
this.m = m;}
String get(int i) { return i < m.length ? m[i] : null; }
String unq(int i) { return unquote(get(i)); }
String tlc(int i) { return unq(i).toLowerCase(); }
boolean bool(int i) { return "true".equals(unq(i)); }
String rest() { return m[m.length-1]; } // for matchStart
int psi(int i) { return Integer.parseInt(unq(i)); }
public String toString() { return "Matches(" + joinWithComma(quoteAll(asList(m))) + ")"; }
public int hashCode() { return _hashCode(toList(m)); }
public boolean equals(Object o) { return o instanceof Matches && arraysEqual(m, ((Matches) o).m); }
}
// for the version with MasterSymbol (used WAY back in "Smart Bot"!) see #1010608
static class Symbol implements CharSequence {
String text;
Symbol() {}
Symbol(String text, boolean dummy) {
this.text = text;} // weird signature to prevent accidental calling
public int hashCode() { return _hashCode(text); }
public String toString() { return text; }
public boolean equals(Object o) {
return this == o;
}
// implementation of CharSequence methods
public int length() { return text.length(); }
public char charAt(int index) { return text.charAt(index); }
public CharSequence subSequence(int start, int end) {
return text.substring(start, end);
}
}
static abstract class F0 {
abstract A get();
}
interface IImageRegion {
// get whole image that the region refers to
public default Img image() { return null; }
// which object made this
public Object creator();
public default int indexInCreator() { return 0; }
// smallest rectangle that all of the region's pixels are contained in
public Rect bounds();
public int numberOfPixels();
public Pt firstPixel();
public Iterator pixelIterator();
public boolean contains(int x, int y);
// gets the region's color (what exactly this means is defined
// by the crea)
public RGB color();
public int brightness();
}
static abstract class F1 {
abstract B get(A a);
}
// you still need to implement hasNext() and next()
static abstract class IterableIterator implements Iterator , Iterable {
public Iterator iterator() {
return this;
}
public void remove() {
unsupportedOperation();
}
}
static final class BWImage extends Meta implements MakesBufferedImage, IBWImage {
int width, height;
byte[] pixels;
// color returned when getPixel is called with a position outside the actual image
float borderColor = 0.0f;
// for unstructure()
BWImage() {}
// BLACK!
BWImage(int width, int height) {
this.height = height;
this.width = width;
pixels = new byte[width*height];
}
BWImage(int width, int height, float brightness) {
this.height = height;
this.width = width;
pixels = new byte[width*height];
fillArrayUnlessZero(pixels, _toByte(brightness));
}
BWImage(int width, int height, float[] pixels) {
this.pixels = new byte[pixels.length];
this.height = height;
this.width = width;
for (int i = 0; i < pixels.length; i++)
this.pixels[i] = _toByte(pixels[i]);
}
public BWImage(int width, int height, byte[] pixels) {
this.height = height;
this.width = width;
this.pixels = pixels;
}
public BWImage(BWImage image) {
width = image.getWidth();
height = image.getHeight();
byte[] pixels = this.pixels = new byte[width*height];
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
pixels[y*width+x] = image.getByte(x, y);
}
// TODO: optimize!
BWImage(RGBImage image) {
width = image.getWidth();
height = image.getHeight();
byte[] pixels = this.pixels = new byte[height*width];
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++) {
RGB rgb = image.getRGB(x, y);
pixels[y*width+x] = BWImage._toByte(rgb.getBrightness());
}
}
/*public BWImage(BufferedImage image) {
this(new RGBImage(image));
}*/
BWImage(BufferedImage image) { try {
width = image.getWidth();
height = image.getHeight();
int[] pixels = new int[width*height];
byte[] bytePixels = this.pixels = new byte[width*height];
PixelGrabber pixelGrabber = new PixelGrabber(image, 0, 0, width, height, pixels, 0, width);
if (!pixelGrabber.grabPixels())
throw fail("Could not grab pixels");
int n = width*height;
for (int i = 0; i < n; i++) {
//bytePixels[i] = pixelToByte(pixels[i]);
int packed = pixels[i];
/*float r = ((packed >> 16) & 0xFF)/255f;
float g = ((packed >> 8) & 0xFF)/255f;
float b = (packed & 0xFF)/255f;
bytePixels[i] = (byte) iround((r+g+b)/3.0f*255f);*/
int r = ((packed >> 16) & 0xFF);
int g = ((packed >> 8) & 0xFF);
int b = (packed & 0xFF);
bytePixels[i] = (byte) ((r+g+b+1)/3);
}
} catch (Exception __e) { throw rethrow(__e); } }
// TODO: does it exactly match the other method? (asRGB+getBrightness+_toByte)
static byte pixelToByte(int packed) {
/*int r = (packed >> 16) & 0xFF;
int g = (packed >> 8) & 0xFF;
int b = packed & 0xFF;
ret (byte) ((r+g+b)/3.0f);*/
float r = ((packed >> 16) & 0xFF)/255f;
float g = ((packed >> 8) & 0xFF)/255f;
float b = (packed & 0xFF)/255f;
return (byte) ((r+g+b)/3.0f*255f);
}
public byte getByte(int x, int y) {
return inRange(x, y) ? getByte_noRangeCheck(x, y) : _toByte(borderColor);
}
// pretty bad function name
// gets brightness (0 to 255) at pixel
int getInt(int x, int y) {
return ubyteToInt(getByte(x, y));
}
public double averageBrightness() {
double sum = 0;
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
sum += getPixel(x, y);
return (sum/(double) (height*width));
}
public float minimumBrightness() {
float min = 1;
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
min = Math.min(min, getPixel(x, y));
return min;
}
public float maximumBrightness() {
float max = 0;
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
max = Math.max(max, getPixel(x, y));
return max;
}
float getPixel(int x, int y) {
return inRange(x, y) ? _toFloat(getByte(x,y )) : borderColor;
}
public float getFloatPixel(int x, int y) { return getPixel(x, y); }
float getPixel(Pt p) { return getPixel(p.x, p.y); }
static byte _toByte(float pixel) {
return (byte) (pixel*255f);
}
static float _toFloat(byte pixel) {
return (((int) pixel) & 255)/255f;
}
private boolean inRange(int x, int y) {
return x >= 0 && x < width && y >= 0 && y < height;
}
public int getWidth() { return width; }
int w() { return width; }
public int getHeight() { return height; }
int h() { return height; }
public RGBImage toRGB() {
int[] rgbs = new int[width*height];
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++) {
int b = getByte(x, y) & 0xFF;
rgbs[y*width+x] = 0xFF000000 | b*0x010101;
}
return new RGBImage(width, height, rgbs);
}
public RGBImage toRGB_slow() {
RGB[] rgbs = new RGB[width*height];
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++) {
float p = getPixel(x, y);
rgbs[y*width+x] = new RGB(p, p, p);
}
return new RGBImage(width, height, rgbs);
}
public BWImage clip(int x, int y, int w, int h) {
return clip(new Rectangle(x, y, w, h));
}
private Rectangle fixClipRect(Rectangle r) {
return r.intersection(new Rectangle(0, 0, width, height));
}
BWImage clip(Rect r) {
return clip(r.getRectangle());
}
/** this should be multithread-safe */
public BWImage clip(Rectangle r) {
r = fixClipRect(r);
byte[] newPixels = new byte[r.height*r.width];
for (int y = 0; y < r.height; y++)
for (int x = 0; x < r.width; x++)
newPixels[y*r.width+x] = getByte(r.x+x, r.y+y);
return new BWImage(r.width, r.height, newPixels);
}
public void setPixel(int x, int y, float brightness) {
setByte(x, y, _toByte(fixPixel(brightness)));
}
// i = 0 to 255
public void setInt(int x, int y, int i) {
setByte(x, y, (byte) limitToUByte(i));
}
public void setByte(int x, int y, byte b) {
if (x >= 0 && x < width && y >= 0 && y < height)
pixels[y*width+x] = b;
}
byte getByte_noRangeCheck(int x, int y) {
return pixels[y*width+x];
}
public void setByte(int x, int y, int brightness) {
setByte(x, y, (byte) brightness);
}
private float fixPixel(float pixel) {
return Math.max(0, Math.min(1, pixel));
}
public float getBorderColor() {
return borderColor;
}
public void setBorderColor(float borderColor) {
this.borderColor = borderColor;
}
public boolean anyPixelBrighterThan(double threshold) {
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
if (getPixel(x, y) > threshold)
return true;
return false;
}
int[] getRGBPixels() {
int n = width*height;
int[] out = new int[n];
for (int i = 0; i < n; i++) {
var b = ubyteToInt(pixels[i]);
b |= (b << 8) | (b << 16);
out[i] = b | 0xFF000000;
}
return out;
}
public BufferedImage getBufferedImage() {
return bufferedImage(getRGBPixels(), width, height);
}
byte[] getBytes() {
return pixels;
}
}
static class MultiMap {
Map > data = new HashMap >();
int fullSize;
MultiMap() {}
MultiMap(boolean useTreeMap) { if (useTreeMap) data = new TreeMap(); }
MultiMap(MultiMap map) { putAll(map); }
MultiMap(Map > data) {
this.data = data;}
void put(A key, B value) { synchronized(data) {
List list = data.get(key);
if (list == null)
data.put(key, list = _makeEmptyList());
list.add(value);
++fullSize;
}}
void add(A key, B value) { put(key, value); }
void addAll(A key, Collection values) { putAll(key, values); }
void addAllIfNotThere(A key, Collection values) { synchronized(data) {
for (B value : values)
setPut(key, value);
}}
void setPut(A key, B value) { synchronized(data) {
if (!containsPair(key, value))
put(key, value);
}}
boolean containsPair(A key, B value) { synchronized(data) {
return get(key).contains(value);
}}
void putAll(Collection keys, B value) { synchronized(data) {
for (A key : unnullForIteration(keys))
put(key, value);
}}
void putAll(A key, Collection values) { synchronized(data) {
if (nempty(values)) getActual(key).addAll(values);
}}
void putAll(Iterable> pairs) { synchronized(data) {
for (Pair p : unnullForIteration(pairs))
put(p.a, p.b);
}}
void removeAll(A key, Collection values) { synchronized(data) {
for (B value : values)
remove(key, value);
}}
List get(A key) { synchronized(data) {
List list = data.get(key);
return list == null ? Collections. emptyList() : list;
}}
List getOpt(A key) { synchronized(data) {
return data.get(key);
}}
List getAndClear(A key) { synchronized(data) {
List l = cloneList(data.get(key));
remove(key);
return l;
}}
// returns actual mutable live list
// creates the list if not there
List getActual(A key) { synchronized(data) {
List list = data.get(key);
if (list == null)
data.put(key, list = _makeEmptyList());
return list;
}}
void clean(A key) { synchronized(data) {
List list = data.get(key);
if (list != null && list.isEmpty()) {
fullSize -= l(list);
data.remove(key);
}
}}
Set keySet() { synchronized(data) {
return data.keySet();
}}
Set keys() { synchronized(data) {
return data.keySet();
}}
void remove(A key) { synchronized(data) {
fullSize -= l(this.getOpt(key));
data.remove(key);
}}
final void remove(Pair p){ removePair(p); }
void removePair(Pair p) {
if (p != null) remove(p.a, p.b);
}
void remove(A key, B value) { synchronized(data) {
List list = data.get(key);
if (list != null) {
if (list.remove(value))
fullSize--;
if (list.isEmpty())
data.remove(key);
}
}}
void clear() { synchronized(data) {
data.clear();
}}
boolean containsKey(A key) { synchronized(data) {
return data.containsKey(key);
}}
B getFirst(A key) { synchronized(data) {
List list = get(key);
return list.isEmpty() ? null : list.get(0);
}}
void addAll(MultiMap map) { putAll(map); }
void putAll(MultiMap map) { synchronized(data) {
for (A key : map.keySet())
putAll(key, map.get(key));
}}
void putAll(Map map) { synchronized(data) {
if (map != null) for (Map.Entry e : map.entrySet())
put(e.getKey(), e.getValue());
}}
final int keyCount(){ return keysSize(); }
int keysSize() { synchronized(data) { return l(data); }}
// full size - note: expensive operation
final int fullSize(){ return size(); }
int size() { synchronized(data) {
return fullSize;
}}
// expensive operation
List reverseGet(B b) { synchronized(data) {
List l = new ArrayList();
for (A key : data.keySet())
if (data.get(key).contains(b))
l.add(key);
return l;
}}
Map > asMap() { synchronized(data) {
return cloneMap(data);
}}
boolean isEmpty() { synchronized(data) { return data.isEmpty(); }}
// override in subclasses
List _makeEmptyList() {
return new ArrayList();
}
// returns live lists
Collection> allLists() {
synchronized(data) {
return new ArrayList(data.values());
}
}
Collection> values() { return allLists(); }
List allValues() {
return concatLists(data.values());
}
Object mutex() { return data; }
public String toString() { return "mm" + str(data); }
}
static interface IF0 {
A get();
}
static interface Hasher {
int hashCode(A a);
boolean equals(A a, A b);
}
// S&P, then regions
static class Gazelle22_ImageToRegions {
BufferedImage inputImage;
Decolorizer decolorizer; // null for simple decolorization
BWIntegralImage ii;
SnPSettings snpSettings;
BWImage posterized;
FastRegions_BWImage regions;
Map, Double> scoredRegions;
FunctionTimings timings;
Gazelle22_ImageToRegions(FunctionTimings timings, BufferedImage inputImage, SnPSettings snpSettings) {
this.snpSettings = snpSettings;
this.inputImage = inputImage;
this.timings = timings;}
public void run() { try {
timings.dO(decolorizer != null ? "bwIntegralImage w/decolorizer" : "bwIntegralImage", () ->
ii = bwIntegralImage_withMeta(inputImage, decolorizer));
timings.dO("scaleAndPosterize", () ->
posterized = scaleAndPosterize(ii, snpSettings));
regions = new FastRegions_BWImage(posterized);
regions.collectBounds();
timings.dO("Regions", regions);
} catch (Exception __e) { throw rethrow(__e); } }
// information about original screenshot if available
ScreenShotMeta screenShotMeta() {
return optCast(ScreenShotMeta.class, getMetaSrc(inputImage));
}
Pt coordinatesFromScreen(Pt p) {
var meta = screenShotMeta();
if (meta == null) return null;
var r = meta.bounds;
if (!r.contains(p)) return null;
p = translatePt(p, -r.x, -r.y);
return scalePt(p, doubleRatio(snpSettings.pixelRows, r.h));
}
Pt coordinatesToScreen(Pt p) {
var meta = screenShotMeta();
if (meta == null) return null;
var r = meta.bounds;
return translatePt(r.x, r.y,
scalePt(p, doubleRatio(r.h, snpSettings.pixelRows)));
}
}
static interface IF1 {
B get(A a);
}
/*
* @(#)WeakHashMap.java 1.5 98/09/30
*
* Copyright 1998 by Sun Microsystems, Inc.,
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
* All rights reserved.
*
* This software is the confidential and proprietary information
* of Sun Microsystems, Inc. ("Confidential Information"). You
* shall not disclose such Confidential Information and shall use
* it only in accordance with the terms of the license agreement
* you entered into with Sun.
*/
// From https://github.com/mernst/plume-lib/blob/df0bfafc3c16848d88f4ea0ef3c8bf3367ae085e/java/src/plume/WeakHasherMap.java
static final class WeakHasherMap extends AbstractMap implements Map {
private Hasher hasher = null;
/*@Pure*/
private boolean keyEquals(Object k1, Object k2) {
return (hasher==null ? k1.equals(k2)
: hasher.equals(k1, k2));
}
/*@Pure*/
private int keyHashCode(Object k1) {
return (hasher==null ? k1.hashCode()
: hasher.hashCode(k1));
}
// The WeakKey class can't be static because it depends on the hasher.
// That in turn means that its methods can't be static.
// However, I need to be able to call the methods such as create() that
// were static in the original version of this code.
// This finesses that.
private /*@Nullable*/ WeakKey WeakKeyCreate(K k) {
if (k == null) return null;
else return new WeakKey(k);
}
private /*@Nullable*/ WeakKey WeakKeyCreate(K k, ReferenceQueue super K> q) {
if (k == null) return null;
else return new WeakKey(k, q);
}
// Cannot be a static class: uses keyHashCode() and keyEquals()
private final class WeakKey extends WeakReference {
private int hash; /* Hashcode of key, stored here since the key
may be tossed by the GC */
private WeakKey(K k) {
super(k);
hash = keyHashCode(k);
}
private /*@Nullable*/ WeakKey create(K k) {
if (k == null) return null;
else return new WeakKey(k);
}
private WeakKey(K k, ReferenceQueue super K> q) {
super(k, q);
hash = keyHashCode(k);
}
private /*@Nullable*/ WeakKey create(K k, ReferenceQueue super K> q) {
if (k == null) return null;
else return new WeakKey(k, q);
}
/* A WeakKey is equal to another WeakKey iff they both refer to objects
that are, in turn, equal according to their own equals methods */
/*@Pure*/
@Override
public boolean equals(/*@Nullable*/ Object o) {
if (o == null) return false; // never happens
if (this == o) return true;
// This test is illegal because WeakKey is a generic type,
// so use the getClass hack below instead.
// if (!(o instanceof WeakKey)) return false;
if (!(o.getClass().equals(WeakKey.class))) return false;
Object t = this.get();
@SuppressWarnings("unchecked")
Object u = ((WeakKey)o).get();
if ((t == null) || (u == null)) return false;
if (t == u) return true;
return keyEquals(t, u);
}
/*@Pure*/
@Override
public int hashCode() {
return hash;
}
}
/* Hash table mapping WeakKeys to values */
private HashMap hash;
/* Reference queue for cleared WeakKeys */
private ReferenceQueue super K> queue = new ReferenceQueue();
/* Remove all invalidated entries from the map, that is, remove all entries
whose keys have been discarded. This method should be invoked once by
each public mutator in this class. We don't invoke this method in
public accessors because that can lead to surprising
ConcurrentModificationExceptions. */
@SuppressWarnings("unchecked")
private void processQueue() {
WeakKey wk;
while ((wk = (WeakKey)queue.poll()) != null) { // unchecked cast
hash.remove(wk);
}
}
/* -- Constructors -- */
/**
* Constructs a new, empty WeakHashMap with the given
* initial capacity and the given load factor.
*
* @param initialCapacity the initial capacity of the
* WeakHashMap
*
* @param loadFactor the load factor of the WeakHashMap
*
* @throws IllegalArgumentException If the initial capacity is less than
* zero, or if the load factor is
* nonpositive
*/
public WeakHasherMap(int initialCapacity, float loadFactor) {
hash = new HashMap(initialCapacity, loadFactor);
}
/**
* Constructs a new, empty WeakHashMap with the given
* initial capacity and the default load factor, which is
* 0.75.
*
* @param initialCapacity the initial capacity of the
* WeakHashMap
*
* @throws IllegalArgumentException If the initial capacity is less than
* zero
*/
public WeakHasherMap(int initialCapacity) {
hash = new HashMap(initialCapacity);
}
/**
* Constructs a new, empty WeakHashMap with the default
* capacity and the default load factor, which is 0.75.
*/
public WeakHasherMap() {
hash = new HashMap();
}
/**
* Constructs a new, empty WeakHashMap with the default
* capacity and the default load factor, which is 0.75.
* The WeakHashMap uses the specified hasher for hashing
* keys and comparing them for equality.
* @param h the Hasher to use when hashing values for this map
*/
public WeakHasherMap(Hasher h) {
hash = new HashMap();
hasher = h;
}
/* -- Simple queries -- */
/**
* Returns the number of key-value mappings in this map.
* Note: In contrast to most implementations of the
* Map interface, the time required by this operation is
* linear in the size of the map.
*/
/*@Pure*/
@Override
public int size() {
return entrySet().size();
}
/**
* Returns true if this map contains no key-value mappings.
*/
/*@Pure*/
@Override
public boolean isEmpty() {
return entrySet().isEmpty();
}
/**
* Returns true if this map contains a mapping for the
* specified key.
*
* @param key the key whose presence in this map is to be tested
*/
/*@Pure*/
@Override
public boolean containsKey(Object key) {
@SuppressWarnings("unchecked")
K kkey = (K) key;
return hash.containsKey(WeakKeyCreate(kkey));
}
/* -- Lookup and modification operations -- */
/**
* Returns the value to which this map maps the specified key.
* If this map does not contain a value for this key, then return
* null.
*
* @param key the key whose associated value, if any, is to be returned
*/
/*@Pure*/
@Override
public /*@Nullable*/ V get(Object key) { // type of argument is Object, not K
@SuppressWarnings("unchecked")
K kkey = (K) key;
return hash.get(WeakKeyCreate(kkey));
}
/**
* Updates this map so that the given key maps to the given
* value. If the map previously contained a mapping for
* key then that mapping is replaced and the previous value is
* returned.
*
* @param key the key that is to be mapped to the given
* value
* @param value the value to which the given key is to be
* mapped
*
* @return the previous value to which this key was mapped, or
* null if if there was no mapping for the key
*/
@Override
public V put(K key, V value) {
processQueue();
return hash.put(WeakKeyCreate(key, queue), value);
}
/**
* Removes the mapping for the given key from this map, if
* present.
*
* @param key the key whose mapping is to be removed
*
* @return the value to which this key was mapped, or null if
* there was no mapping for the key
*/
@Override
public V remove(Object key) { // type of argument is Object, not K
processQueue();
@SuppressWarnings("unchecked")
K kkey = (K) key;
return hash.remove(WeakKeyCreate(kkey));
}
/**
* Removes all mappings from this map.
*/
@Override
public void clear() {
processQueue();
hash.clear();
}
/* -- Views -- */
/* Internal class for entries */
// This can't be static, again because of dependence on hasher.
@SuppressWarnings("TypeParameterShadowing")
private final class Entry implements Map.Entry {
private Map.Entry ent;
private K key; /* Strong reference to key, so that the GC
will leave it alone as long as this Entry
exists */
Entry(Map.Entry ent, K key) {
this.ent = ent;
this.key = key;
}
/*@Pure*/
@Override
public K getKey() {
return key;
}
/*@Pure*/
@Override
public V getValue() {
return ent.getValue();
}
@Override
public V setValue(V value) {
return ent.setValue(value);
}
/*@Pure*/
private boolean keyvalEquals(K o1, K o2) {
return (o1 == null) ? (o2 == null) : keyEquals(o1, o2);
}
/*@Pure*/
private boolean valEquals(V o1, V o2) {
return (o1 == null) ? (o2 == null) : o1.equals(o2);
}
/*@Pure*/
@SuppressWarnings("NonOverridingEquals")
public boolean equals(Map.Entry e /* Object o*/) {
// if (! (o instanceof Map.Entry)) return false;
// Map.Entry e = (Map.Entry)o;
return (keyvalEquals(key, e.getKey())
&& valEquals(getValue(), e.getValue()));
}
/*@Pure*/
@Override
public int hashCode() {
V v;
return (((key == null) ? 0 : keyHashCode(key))
^ (((v = getValue()) == null) ? 0 : v.hashCode()));
}
}
/* Internal class for entry sets */
private final class EntrySet extends AbstractSet> {
Set> hashEntrySet = hash.entrySet();
@Override
public Iterator> iterator() {
return new Iterator>() {
Iterator> hashIterator = hashEntrySet.iterator();
Map.Entry next = null;
@Override
public boolean hasNext() {
while (hashIterator.hasNext()) {
Map.Entry ent = hashIterator.next();
WeakKey wk = ent.getKey();
K k = null;
if ((wk != null) && ((k = wk.get()) == null)) {
/* Weak key has been cleared by GC */
continue;
}
next = new Entry(ent, k);
return true;
}
return false;
}
@Override
public Map.Entry next() {
if ((next == null) && !hasNext())
throw new NoSuchElementException();
Map.Entry e = next;
next = null;
return e;
}
@Override
public void remove() {
hashIterator.remove();
}
};
}
/*@Pure*/
@Override
public boolean isEmpty() {
return !(iterator().hasNext());
}
/*@Pure*/
@Override
public int size() {
int j = 0;
for (Iterator> i = iterator(); i.hasNext(); i.next()) j++;
return j;
}
@Override
public boolean remove(Object o) {
processQueue();
if (!(o instanceof Map.Entry,?>)) return false;
@SuppressWarnings("unchecked")
Map.Entry e = (Map.Entry)o; // unchecked cast
Object ev = e.getValue();
WeakKey wk = WeakKeyCreate(e.getKey());
Object hv = hash.get(wk);
if ((hv == null)
? ((ev == null) && hash.containsKey(wk)) : hv.equals(ev)) {
hash.remove(wk);
return true;
}
return false;
}
/*@Pure*/
@Override
public int hashCode() {
int h = 0;
for (Iterator> i = hashEntrySet.iterator(); i.hasNext(); ) {
Map.Entry ent = i.next();
WeakKey wk = ent.getKey();
Object v;
if (wk == null) continue;
h += (wk.hashCode()
^ (((v = ent.getValue()) == null) ? 0 : v.hashCode()));
}
return h;
}
}
private /*@Nullable*/ Set> entrySet = null;
/**
* Returns a Set view of the mappings in this map.
*/
/*@SideEffectFree*/
@Override
public Set> entrySet() {
if (entrySet == null) entrySet = new EntrySet();
return entrySet;
}
// find matching key
K findKey(Object key) {
processQueue();
K kkey = (K) key;
// TODO: use replacement for HashMap to avoid reflection
WeakKey wkey = WeakKeyCreate(kkey);
WeakKey found = hashMap_findKey(hash, wkey);
return found == null ? null : found.get();
}
}
static class PersistableThrowable extends DynamicObject {
String className;
String msg;
String stacktrace;
PersistableThrowable() {}
PersistableThrowable(Throwable e) {
if (e == null)
className = "Crazy Null Error";
else {
className = getClassName(e).replace('/', '.');
msg = e.getMessage();
stacktrace = getStackTrace_noRecord(e);
}
}
public String toString() {
return nempty(msg) ? className + ": " + msg : className;
}
}
// See GazelleV_LeftArrowScriptParser
// TODO: decide whether we allow calling methods/getting fields on
// a null reference (just returning null), or whether we throw a
// NullPointerException.
static class GazelleV_LeftArrowScript {
abstract static class Base implements IHasTokenRangeWithSrc {
TokenRangeWithSrc src;
public void setTokenRangeWithSrc(TokenRangeWithSrc src) { this.src = src; }
public TokenRangeWithSrc tokenRangeWithSrc() { return src; }
RuntimeException rethrowWithSrc(Throwable e) {
if (src != null)
throw rethrowAndAppendToMessage(e, squareBracketed(str(src)));
else
throw rethrow(e);
}
}
interface Evaluable {
public default Object get() { return get(new VarContext()); }
public Object get(VarContext ctx);
}
// We're using SynchronizedList as a list wrapper
//sclass Script extends ArrayList {
static class Script extends SynchronizedList implements Evaluable {
Map functionDefs;
Script() { super(new ArrayList()); }
public Object get(VarContext ctx) {
Object result = null;
for (var step : this) {
ping();
result = step.get(ctx);
}
return result;
}
public String toString() { return pnlToLines(this); }
FunctionDef getFunction(String name) { return mapGet(functionDefs, name); }
} // end of Script
static class FunctionDef extends Base implements IFieldsToList{
String name;
List args;
Evaluable body;
FunctionDef() {}
FunctionDef(String name, List args, Evaluable body) {
this.body = body;
this.args = args;
this.name = name;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + name + ", " + args + ", " + body + ")"; }public Object[] _fieldsToList() { return new Object[] {name, args, body}; }
public Object call(VarContext ctx, Object... args) {
var ctx2 = new VarContext(ctx);
int n = min(l(args), l(this.args));
for (int i = 0; i < n; i++)
ctx2.put(this.args.get(i), args[i]);
return body.get(ctx2);
}
}
static class Assignment extends Base implements Evaluable , IFieldsToList{
String var;
Evaluable expression;
Assignment() {}
Assignment(String var, Evaluable expression) {
this.expression = expression;
this.var = var;}public Object[] _fieldsToList() { return new Object[] {var, expression}; }
public Object get(VarContext ctx) {
Object o = expression.get(ctx);
ctx.set(var, o);
return o;
}
public String toString() { return var + " <- " + expression; }
}
static class NewObject extends Base implements Evaluable {
NewObject() {}
Class c;
List args;
NewObject(Class c) {
this.c = c;}
NewObject(Class c, List args) {
this.args = args;
this.c = c;}
public Object get(VarContext ctx) {
return callConstructor(c, mapToArray(args, arg -> arg.get(ctx)));
}
public String toString() { return "new " + formatFunctionCall(className(c), args); }
}
static class CallFunction extends Base implements Evaluable , IFieldsToList{
FunctionDef f;
List args;
CallFunction() {}
CallFunction(FunctionDef f, List args) {
this.args = args;
this.f = f;}public Object[] _fieldsToList() { return new Object[] {f, args}; }
public Object get(VarContext ctx) {
//ping();
return f.call(ctx, mapToArray(args, a -> a.get(ctx)));
}
public String toString() { return formatFunctionCall(f.name, args); }
}
static class GetVar extends Base implements Evaluable , IFieldsToList{
String var;
GetVar() {}
GetVar(String var) {
this.var = var;}public Object[] _fieldsToList() { return new Object[] {var}; }
public Object get(VarContext ctx) {
return ctx.get(var);
}
public String toString() { return var; }
}
static class Const extends Base implements Evaluable , IFieldsToList{
Object value;
Const() {}
Const(Object value) {
this.value = value;}public Object[] _fieldsToList() { return new Object[] {value}; }
public Object get(VarContext ctx) {
return value;
}
public String toString() { return strOrClassName(value); }
}
static class GetStaticField extends Base implements Evaluable , IFieldsToList{
Field field;
GetStaticField() {}
GetStaticField(Field field) {
this.field = field;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + field + ")"; }public Object[] _fieldsToList() { return new Object[] {field}; }
public Object get(VarContext ctx) { try {
return field.get(null);
} catch (Exception __e) { throw rethrow(__e); } }
}
static class CallMethodOrGetField extends Base implements Evaluable , IFieldsToList{
Evaluable target;
String name;
CallMethodOrGetField() {}
CallMethodOrGetField(Evaluable target, String name) {
this.name = name;
this.target = target;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + target + ", " + name + ")"; }public Object[] _fieldsToList() { return new Object[] {target, name}; }
public Object get(VarContext ctx) {
try {
Object object = target.get(ctx);
if (object == null)
return null; // throw new NullPointerException();
// could optimize more for sure
if (canCallWithVarargs(object, name))
return call(object, name);
return _get(object, name);
} catch (Throwable e) {
throw rethrowWithSrc(e);
}
}
}
static class CallMethod extends Base implements Evaluable , IFieldsToList{
static final String _fieldOrder = "target methodName args";
Evaluable target;
String methodName;
List args;
CallMethod() {}
CallMethod(Evaluable target, String methodName, List args) {
this.args = args;
this.methodName = methodName;
this.target = target;}
public boolean equals(Object o) {
if (!(o instanceof CallMethod)) return false;
CallMethod __1 = (CallMethod) o;
return eq(target, __1.target) && eq(methodName, __1.methodName) && eq(args, __1.args);
}
public int hashCode() {
int h = -898542337;
h = boostHashCombine(h, _hashCode(target));
h = boostHashCombine(h, _hashCode(methodName));
h = boostHashCombine(h, _hashCode(args));
return h;
}
public Object[] _fieldsToList() { return new Object[] {target, methodName, args}; }
public Object get(VarContext ctx) {
return call(target.get(ctx), methodName, mapToArray(args, arg -> arg.get(ctx)));
}
public String toString() { return target + "." + formatFunctionCall(methodName, args); }
}
static class While extends Base implements Evaluable , IFieldsToList{
static final String _fieldOrder = "condition body";
Evaluable condition;
Evaluable body;
While() {}
While(Evaluable condition, Evaluable body) {
this.body = body;
this.condition = condition;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + condition + ", " + body + ")"; }
public boolean equals(Object o) {
if (!(o instanceof While)) return false;
While __2 = (While) o;
return eq(condition, __2.condition) && eq(body, __2.body);
}
public int hashCode() {
int h = 83548945;
h = boostHashCombine(h, _hashCode(condition));
h = boostHashCombine(h, _hashCode(body));
return h;
}
public Object[] _fieldsToList() { return new Object[] {condition, body}; }
public Object get(VarContext ctx) {
while (ping() && (Boolean) condition.get(ctx)) {
body.get(ctx);
}
// while loops don't return anything
return null;
}
}
static class ForEach extends Base implements Evaluable , IFieldsToList{
static final String _fieldOrder = "collection var body";
Evaluable collection;
String var;
Evaluable body;
ForEach() {}
ForEach(Evaluable collection, String var, Evaluable body) {
this.body = body;
this.var = var;
this.collection = collection;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + collection + ", " + var + ", " + body + ")"; }
public boolean equals(Object o) {
if (!(o instanceof ForEach)) return false;
ForEach __3 = (ForEach) o;
return eq(collection, __3.collection) && eq(var, __3.var) && eq(body, __3.body);
}
public int hashCode() {
int h = 986017354;
h = boostHashCombine(h, _hashCode(collection));
h = boostHashCombine(h, _hashCode(var));
h = boostHashCombine(h, _hashCode(body));
return h;
}
public Object[] _fieldsToList() { return new Object[] {collection, var, body}; }
public Object get(VarContext ctx) {
var coll = collection.get(ctx);
Iterator iterator;
if (coll instanceof Object[])
for (var element : ((Object[]) coll)) {
ping();
ctx.set(var, element);
body.get(ctx);
}
else if (coll instanceof Iterable) {
for (var element : ((Iterable) coll)) {
ping();
ctx.set(var, element);
body.get(ctx);
}
} else if (coll == null) {} // ok
else
throw fail("Not iterable: " + className(coll));
ctx.unset(var);
return null;
}
}
static class IfThen extends Base implements Evaluable , IFieldsToList{
static final String _fieldOrder = "condition body";
Evaluable condition;
Evaluable body;
IfThen() {}
IfThen(Evaluable condition, Evaluable body) {
this.body = body;
this.condition = condition;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + condition + ", " + body + ")"; }
public boolean equals(Object o) {
if (!(o instanceof IfThen)) return false;
IfThen __4 = (IfThen) o;
return eq(condition, __4.condition) && eq(body, __4.body);
}
public int hashCode() {
int h = -2108234502;
h = boostHashCombine(h, _hashCode(condition));
h = boostHashCombine(h, _hashCode(body));
return h;
}
public Object[] _fieldsToList() { return new Object[] {condition, body}; }
public Object get(VarContext ctx) {
if ((Boolean) condition.get(ctx))
return body.get(ctx);
else
return null;
}
}
}
static interface IVF1 {
void get(A a);
}
static class Fail extends RuntimeException implements IFieldsToList{
Object[] objects;
Fail() {}
Fail(Object... objects) {
this.objects = objects;}public Object[] _fieldsToList() { return new Object[] {objects}; }
Fail(Throwable cause, Object... objects) {
super(cause);
this.objects = objects;
}
public String toString() { return joinNemptiesWithColon("Fail", commaCombine(getCause(), objects)); }
}
static class Pair implements Comparable> {
A a;
B b;
Pair() {}
Pair(A a, B b) {
this.b = b;
this.a = a;}
public int hashCode() {
return hashCodeFor(a) + 2*hashCodeFor(b);
}
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Pair)) return false;
Pair t = (Pair) o;
return eq(a, t.a) && eq(b, t.b);
}
public String toString() {
return "<" + a + ", " + b + ">";
}
public int compareTo(Pair p) {
if (p == null) return 1;
int i = ((Comparable ) a).compareTo(p.a);
if (i != 0) return i;
return ((Comparable) b).compareTo(p.b);
}
}
// Meta - a "minimal" approach to adding meta-level to Java objects
static class Meta implements IMeta {
// Meta - a "minimal" approach to adding meta-level to Java objects
// (implementing the interface IMeta)
// We allocate one extra field for each Java object to make it
// reasoning-compatible (reasoning-compatible = extensible with
// fields of any name at runtime).
//
// We couldn't go for 0 extra fields (meta values must be linked
// directly from the object) and there are no half fields in
// Java... so there you go.
//
// Also, if you don't use any meta data, you are probably not
// reasoning about anything. The point of reasoning in JavaX is
// to attach information to objects directly used in the program.
// Possible information contained in the meta field:
// Origin, destination, security level, sender, cost center,
// purpose, list of reifications, ...
// So here it is. THE FIELD YOU HAVE BEEN WAITING FOR!
// [We also have IMeta to retrofit foreign classes (rare but
// probably useful).]
//////////////////////
// The "meta" field //
//////////////////////
// Generic meta value of any kind, but the typical case is it's a
// Map with extra field values for the object etc.
// "meta" is volatile to avoid synchronization; but you can also synchronize on
// _tempMetaMutex() which is usually the object itself. Collections
// and maps are exempt from using the collections's monitor as the meta
// mutex because their monitor tends to be held for long operations
// (e.g. cloneList). For those we use a substantially more complex
// algorithm using a weakMap. Probably overkill. I may reconsider.
volatile Object meta;
// The meta field is not transient, thus by default it will be
// persisted like anything else unless you customize your object
// to suppress or modulate this.
// ...and the interface methods
public void _setMeta(Object meta) { this.meta = meta; }
public Object _getMeta() { return meta; }
// MOST functions are implemented in IMeta (default implementations)
}
// function type is A (e.g. String)
static class FunctionTimings {
Map data = syncMap();
final void time(A function, Runnable r){ dO(function, r); }
void dO(A function, Runnable r) {
if (r == null) return;
Average avg = syncMapGetOrCreate(data, function, () -> new Average());
long time = nanoTime();
try {
r.run();
} finally {
time = nanoTime()-time;
avg.add(time);
}
}
Map get() { return cloneMap(data); }
final void clear(){ reset(); }
void reset() { data.clear(); }
// as multi-line string, sorted alphabetically
String render() {
return lines(ciSorted(map(get(), (f, avg) ->
functionToString(f) + ": " + n2(iround(nsToMicroseconds(avg.get())))
+ " " + microSymbol() + "s (" + n2(iround(avg.n())) + ")")));
}
String functionToString(A f) {
return firstToUpper(str(f));
}
}
final static class Rect implements IFieldsToList{
static final String _fieldOrder = "x y w h";
int x;
int y;
int w;
int h;
Rect() {}
Rect(int x, int y, int w, int h) {
this.h = h;
this.w = w;
this.y = y;
this.x = x;}
public boolean equals(Object o) {
if (!(o instanceof Rect)) return false;
Rect __1 = (Rect) o;
return x == __1.x && y == __1.y && w == __1.w && h == __1.h;
}
public int hashCode() {
int h = 2543108;
h = boostHashCombine(h, _hashCode(x));
h = boostHashCombine(h, _hashCode(y));
h = boostHashCombine(h, _hashCode(w));
h = boostHashCombine(h, _hashCode(h));
return h;
}
public Object[] _fieldsToList() { return new Object[] {x, y, w, h}; }
Rect(Rectangle r) {
x = r.x;
y = r.y;
w = r.width;
h = r.height;
}
Rect(Pt p, int w, int h) {
this.h = h;
this.w = w; x = p.x; y = p.y; }
Rect(Rect r) { x = r.x; y = r.y; w = r.w; h = r.h; }
Rectangle getRectangle() {
return new Rectangle(x, y, w, h);
}
public String toString() {
return x + "," + y + " / " + w + "," + h;
}
int x1() { return x; }
int y1() { return y; }
int x2() { return x + w; }
int y2() { return y + h; }
boolean contains(Pt p) {
return contains(p.x, p.y);
}
boolean contains(int _x, int _y) {
return _x >= x && _y >= y && _x < x+w && _y < y+h;
}
boolean contains(Rectangle r) {
return rectContains(this, r);
}
boolean empty() { return w <= 0 || h <= 0; }
int getWidth() { return w; }
int getHeight() { return h; }
}
static class TokenRangeWithSrc extends TokenRange {
List tok;
TokenRangeWithSrc() {}
TokenRangeWithSrc(List tok, int start) {
this.start = start; end = start; }
TokenRangeWithSrc(List tok, int start, int end) {
this.end = end;
this.start = start;}
TokenRangeWithSrc(ListAndIndex startPtr, ListAndIndex endPtr) {
assertSame(tok = startPtr.list(), endPtr.list());
start = startPtr.idx();
end = endPtr.idx();
}
ListAndIndex startPtr() { return new ListAndIndex(tok, start); }
ListAndIndex endPtr() { return new ListAndIndex(tok, end); }
LineAndColumn startLineAndCol() { return tokenToLineAndColumn(startPtr()); }
LineAndColumn endLineAndCol() { return tokenToLineAndColumn(endPtr()); }
public String toString() {
var start = startLineAndCol();
if (eq(start, end)) return str(start);
return start + " to " + endLineAndCol();
}
}
static interface IBWImage extends MakesBufferedImage {
float getFloatPixel(int x, int y); // usually between 0 and 1
default float getFloatPixel(Pt p) { return getFloatPixel(p.x, p.y); }
public default BufferedImage getBufferedImage() {
return grayImageFromIBWImage(this);
}
}
static class Pt implements Comparable, IDoublePt {
int x, y;
Pt() {}
Pt(Point p) {
x = p.x;
y = p.y;
}
Pt(int x, int y) {
this.y = y;
this.x = x;}
Point getPoint() {
return new Point(x, y);
}
public boolean equals(Object o) {
return o instanceof Pt && x == ((Pt) o).x && y == ((Pt) o).y;
}
public int hashCode() {
return boostHashCombine(x, y);
}
// compare in scan order
public int compareTo(Pt p) {
if (y != p.y) return cmp(y, p.y);
return cmp(x, p.x);
}
public String toString() {
return x + ", " + y;
}
double length() { return sqrt(x*x+y*y); }
Pt minus(Pt p) { return ptMinus(this, p); }
public double x_double() { return x; }
public double y_double() { return y; }
}
static class VarContext {
VarContext parent;
Map vars;
VarContext() {}
VarContext(VarContext parent) {
this.parent = parent;}
Object get(String name) {
if (containsKey(vars, name))
return mapGet(vars, name);
if (parent != null)
return parent.get(name);
return null;
}
final void put(String name, Object value){ set(name, value); }
void set(String name, Object value) {
vars = mapPutOrCreate(vars, name, value);
}
void unset(String name) {
remove(vars, name);
}
}
// SnP = Scale and Posterize
static class SnPSettings implements IFieldsToList{
static final String _fieldOrder = "pixelRows colors";
int pixelRows;
int colors;
SnPSettings(int pixelRows, int colors) {
this.colors = colors;
this.pixelRows = pixelRows;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + pixelRows + ", " + colors + ")"; }
public boolean equals(Object o) {
if (!(o instanceof SnPSettings)) return false;
SnPSettings __1 = (SnPSettings) o;
return pixelRows == __1.pixelRows && colors == __1.colors;
}
public int hashCode() {
int h = -327917448;
h = boostHashCombine(h, _hashCode(pixelRows));
h = boostHashCombine(h, _hashCode(colors));
return h;
}
public Object[] _fieldsToList() { return new Object[] {pixelRows, colors}; }
SnPSettings() { pixelRows = 128; colors = 8; }
// use full image resolution (no downsampling)
SnPSettings(BufferedImage image, int colors) {
pixelRows = image.getHeight();
this.colors = colors;
}
SnPSettings cloneMe() { return shallowClone(this); }
}
static class FailedRule extends RuleWithParams {
List satisfiedConditions;
Exp remainingCondition;
FailedRule() {}
FailedRule(IfThen rule, VarMatches matches, Exp remainingCondition) {
this.remainingCondition = remainingCondition;
this.matches = matches;
this.rule = rule;}
FailedRule(IfThen rule, VarMatches matches, List satisfiedConditions, Exp remainingCondition) {
this.remainingCondition = remainingCondition;
this.satisfiedConditions = satisfiedConditions;
this.matches = matches;
this.rule = rule;}
}
static class RuleWithParams implements IFieldsToList{
static final String _fieldOrder = "rule matches";
IfThen rule;
VarMatches matches;
RuleWithParams() {}
RuleWithParams(IfThen rule, VarMatches matches) {
this.matches = matches;
this.rule = rule;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + rule + ", " + matches + ")"; }
public boolean equals(Object o) {
if (!(o instanceof RuleWithParams)) return false;
RuleWithParams __7 = (RuleWithParams) o;
return eq(rule, __7.rule) && eq(matches, __7.matches);
}
public int hashCode() {
int h = 1254104616;
h = boostHashCombine(h, _hashCode(rule));
h = boostHashCombine(h, _hashCode(matches));
return h;
}
public Object[] _fieldsToList() { return new Object[] {rule, matches}; }
String ruleID() { return rule.globalID; }
}
static class IfThen implements IFieldsToList{
static final String _fieldOrder = "in out globalID options originalText";
Exp in;
Exp out;
IfThen() {}
IfThen(Exp in, Exp out) {
this.out = out;
this.in = in;}
public boolean equals(Object o) {
if (!(o instanceof IfThen)) return false;
IfThen __8 = (IfThen) o;
return eq(in, __8.in) && eq(out, __8.out);
}
public int hashCode() {
int h = -2108234502;
h = boostHashCombine(h, _hashCode(in));
h = boostHashCombine(h, _hashCode(out));
return h;
}
public Object[] _fieldsToList() { return new Object[] {in, out}; }
String globalID;
Set options;
String originalText;
String text() {
Collection opt = options;
if (nempty(globalID)) opt = concatLists(ll("id: " + globalID), opt);
return (nempty(opt) ? "[" + joinWithComma(opt) + "] " : "")
+ (in == null ? "" : in.text() + "\n => ") + nlLogic_text(out);
}
public String toString() { return text(); }
}
abstract static class Exp {
abstract String text();
public String toString() { return text(); }
}
static class Func extends Exp implements IFieldsToList{
String name;
Exp arg;
Func() {}
Func(String name, Exp arg) {
this.arg = arg;
this.name = name;}
public boolean equals(Object o) {
if (!(o instanceof Func)) return false;
Func __0 = (Func) o;
return eq(name, __0.name) && eq(arg, __0.arg);
}
public int hashCode() {
int h = 2201316;
h = boostHashCombine(h, _hashCode(name));
h = boostHashCombine(h, _hashCode(arg));
return h;
}
public Object[] _fieldsToList() { return new Object[] {name, arg}; }
List options;
Func(String name, List options, Exp arg) {
this.arg = arg;
this.options = options;
this.name = name;}
String text() {
return name
+ (empty(options) ? "" : "[" + joinWithComma(options) + "]")
+ "(" + arg.text() + ")";
}
String argText() { return nlLogic_text(arg); }
}
static class And extends Exp implements IFieldsToList{
Exp a;
Exp b;
And() {}
And(Exp a, Exp b) {
this.b = b;
this.a = a;}
public boolean equals(Object o) {
if (!(o instanceof And)) return false;
And __1 = (And) o;
return eq(a, __1.a) && eq(b, __1.b);
}
public int hashCode() {
int h = 65975;
h = boostHashCombine(h, _hashCode(a));
h = boostHashCombine(h, _hashCode(b));
return h;
}
public Object[] _fieldsToList() { return new Object[] {a, b}; }
String text() {
return a.text() + "\n && " + b.text();
}
}
static class ExpNot extends Exp implements IFieldsToList{
Exp a;
ExpNot() {}
ExpNot(Exp a) {
this.a = a;}
public boolean equals(Object o) {
if (!(o instanceof ExpNot)) return false;
ExpNot __2 = (ExpNot) o;
return eq(a, __2.a);
}
public int hashCode() {
int h = 2089649046;
h = boostHashCombine(h, _hashCode(a));
return h;
}
public Object[] _fieldsToList() { return new Object[] {a}; }
String text() {
return "!" + a.text();
}
}
abstract static class Literal extends Exp {}
static class Sentence extends Literal implements IFieldsToList{
List tok;
Sentence() {}
Sentence(List tok) {
this.tok = tok;}
public boolean equals(Object o) {
if (!(o instanceof Sentence)) return false;
Sentence __3 = (Sentence) o;
return eq(tok, __3.tok);
}
public int hashCode() {
int h = 1327381123;
h = boostHashCombine(h, _hashCode(tok));
return h;
}
public Object[] _fieldsToList() { return new Object[] {tok}; }
String text() { return join(tok); } }
static class Sentence2 extends Literal implements IFieldsToList{
String text;
Sentence2() {}
Sentence2(String text) {
this.text = text;}
public boolean equals(Object o) {
if (!(o instanceof Sentence2)) return false;
Sentence2 __4 = (Sentence2) o;
return eq(text, __4.text);
}
public int hashCode() {
int h = -1800858097;
h = boostHashCombine(h, _hashCode(text));
return h;
}
public Object[] _fieldsToList() { return new Object[] {text}; }
String text() { return text; } }
static class Eq extends Exp implements IFieldsToList{
Exp left;
Exp right;
Eq() {}
Eq(Exp left, Exp right) {
this.right = right;
this.left = left;}
public boolean equals(Object o) {
if (!(o instanceof Eq)) return false;
Eq __5 = (Eq) o;
return eq(left, __5.left) && eq(right, __5.right);
}
public int hashCode() {
int h = 2252;
h = boostHashCombine(h, _hashCode(left));
h = boostHashCombine(h, _hashCode(right));
return h;
}
public Object[] _fieldsToList() { return new Object[] {left, right}; }
String text() {
return left.text() + " = " + right.text();
}
}
static class RGB {
// usually in range [0, 1]
public float r, g, b; // can't be final cause persistence
RGB() {}
public RGB(float r, float g, float b) {
this.r = r;
this.g = g;
this.b = b;
}
public RGB(double r, double g, double b) {
this.r = (float) r;
this.g = (float) g;
this.b = (float) b;
}
public RGB(double[] rgb) {
this(rgb[0], rgb[1], rgb[2]);
}
public RGB(int rgb) {
this(new Color(rgb));
}
public RGB(double brightness) {
this.r = this.g = this.b = max(0f, min(1f, (float) brightness));
}
public RGB(Color color) {
this.r = color.getRed()/255f;
this.g = color.getGreen()/255f;
this.b = color.getBlue()/255f;
}
// TODO: 3-char version
public RGB(String hex) {
int i = l(hex)-6;
r = Integer.parseInt(hex.substring(i, i+2), 16)/255f;
g = Integer.parseInt(hex.substring(i+2, i+4), 16)/255f;
b = Integer.parseInt(hex.substring(i+4, i+6), 16)/255f;
}
public float getComponent(int i) {
return i == 0 ? r : i == 1 ? g : b;
}
public int getInt(int i) {
return i == 0 ? redInt() : i == 1 ? greenInt() : blueInt();
}
public Color getColor() {
return new Color(r, g, b);
}
public static RGB newSafe(float r, float g, float b) {
return new RGB(Math.max(0, Math.min(1, r)), Math.max(0, Math.min(1, g)), Math.max(0, Math.min(1, b)));
}
int asInt() { return getColor().getRGB() & 0xFFFFFF; }
int getInt() { return getColor().getRGB() & 0xFFFFFF; }
int asIntWithAlpha() { return rgbInt(redInt(), greenInt(), blueInt()) | 0xFF000000; }
public float getBrightness() {
return (r+g+b)/3.0f;
}
public String getHexString() {
return Integer.toHexString(asInt() | 0xFF000000).substring(2).toUpperCase();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof RGB)) return false;
RGB rgb = (RGB) o;
if (Float.compare(rgb.b, b) != 0) return false;
if (Float.compare(rgb.g, g) != 0) return false;
if (Float.compare(rgb.r, r) != 0) return false;
return true;
}
@Override
public int hashCode() {
int result = (r != +0.0f ? Float.floatToIntBits(r) : 0);
result = 31 * result + (g != +0.0f ? Float.floatToIntBits(g) : 0);
result = 31 * result + (b != +0.0f ? Float.floatToIntBits(b) : 0);
return result;
}
public boolean isBlack() {
return r == 0f && g == 0f && b == 0f;
}
public boolean isWhite() {
return r == 1f && g == 1f && b == 1f;
}
public String toString() {
return getHexString();
}
int redInt() { return iround(r*255); }
int greenInt() { return iround(g*255); }
int blueInt() { return iround(b*255); }
static float brightnessToFloat(int brightness) { return brightness/255f; }
}
static class ScreenShotMeta implements IFieldsToList{
TimestampRange takenWhen;
Rect bounds;
BufferedImage image;
ScreenShotMeta() {}
ScreenShotMeta(TimestampRange takenWhen, Rect bounds, BufferedImage image) {
this.image = image;
this.bounds = bounds;
this.takenWhen = takenWhen;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + takenWhen + ", " + bounds + ", " + image + ")"; }public Object[] _fieldsToList() { return new Object[] {takenWhen, bounds, image}; }
}
static interface MakesBufferedImage extends WidthAndHeight {
BufferedImage getBufferedImage();
public default void drawAt(Graphics2D g, int x, int y) {
g.drawImage(getBufferedImage(), x, y, null);
}
}
// grayscale, actually
static class BWIntegralImage extends Meta implements IBWIntegralImage, IIntegralImage {
int w, h;
int[] data; // 1 entry per pixel
// constructors
BWIntegralImage() {}
BWIntegralImage(File f) { this(loadImage2(f)); }
BWIntegralImage(MakesBufferedImage img) { this(toBufferedImage(img)); }
BWIntegralImage(BufferedImage image) { grab(image); }
BWIntegralImage(BufferedImage image, Decolorizer decolorizer) { grab(image, decolorizer); }
BWIntegralImage(GrabbableIntPixels gp) { grab(gp); }
BWIntegralImage(GrabbableGrayPixels gp) { grab(gp); }
BWIntegralImage(BWImage img) {
grab(new GrabbableGrayPixels(img.pixels, img.width, img.height,
0, img.width));
}
// grab functions
void grab(BufferedImage image) { grab(image, null); }
void grab(BufferedImage image, Decolorizer decolorizer) {
if (image.getType() == BufferedImage.TYPE_BYTE_GRAY)
grab(grabbableGrayPixels(image));
else // rgb image
grab(grabbableIntPixels_fastOrSlow(image), decolorizer);
}
void grab(GrabbableIntPixels gp, Decolorizer decolorizer) {
if (decolorizer == null) { grab(gp); return; }
alloc(gp.w, gp.h);
int w = this.w, h = this.h;
int offset = gp.offset, sum = 0;
int[] image = gp.data;
for (int x = 0; x < w; x++) {
int packed = image[offset+x];
int brightness = decolorizer.toGrayScale(packed);
data[x] = (sum += brightness);
}
var ping = pingSource();
int scanlineExtra = gp.scanlineStride-w;
int iImage = offset+gp.scanlineStride, i = w;
for (int y = 1; y < h; y++) {
sum = 0;
for (int x = 0; x < w; x++) {
int packed = image[iImage];
int brightness = decolorizer.toGrayScale(packed);
sum += brightness;
data[i] = sum + data[i-w];
iImage++; i++;
}
iImage += scanlineExtra;
{ if (ping != null) ping.get(); }
} // for y
}
void grab(GrabbableIntPixels gp) {
alloc(gp.w, gp.h);
int w = this.w, h = this.h;
int offset = gp.offset, sum = 0;
int[] image = gp.data;
for (int x = 0; x < w; x++) {
int packed = image[offset+x];
int brightness = packedToBrightness(packed);
data[x] = (sum += brightness);
}
var ping = pingSource();
int scanlineExtra = gp.scanlineStride-w;
int iImage = offset+gp.scanlineStride, i = w;
for (int y = 1; y < h; y++) {
sum = 0;
for (int x = 0; x < w; x++) {
int packed = image[iImage];
int brightness = packedToBrightness(packed);
sum += brightness;
data[i] = sum + data[i-w];
iImage++; i++;
}
iImage += scanlineExtra;
{ if (ping != null) ping.get(); }
} // for y
}
void grab(GrabbableGrayPixels gp) {
alloc(gp.w, gp.h);
int offset = gp.offset, sum = 0;
byte[] image = gp.data;
for (int x = 0; x < w; x++) {
int brightness = image[offset+x];
data[x] = (sum += brightness);
}
var ping = pingSource();
int scanlineExtra = gp.scanlineStride-w;
int iImage = offset+gp.scanlineStride, i = w;
for (int y = 1; y < h; y++) {
sum = 0;
for (int x = 0; x < w; x++) {
int brightness = image[iImage];
sum += brightness;
data[i] = sum + data[i-w];
iImage++; i++;
}
iImage += scanlineExtra;
{ if (ping != null) ping.get(); }
} // for y
}
private void alloc(int w, int h) {
this.w = w;
this.h = h;
if (w*h > 8*1024*1024)
throw fail("Image too large (more than 8 MP): " + w + "*" + h);
data = new int[w*h];
}
// pixels outside of image are considered black
int get(int x, int y) {
return x < 0 || y < 0 ? 0
: data[min(y, h-1)*w+min(x, w-1)];
}
// precise version with anti-aliasing [TO TEST!]
public double getIIValue(double x, double y) {
int xFloor = ifloor(x), yFloor = ifloor(y);
double val = getIIValue(xFloor, yFloor);
// at integer coordinate?
if (xFloor == x && yFloor == y)
return val;
// at non-integer coordinate, perform subpixel calculation
double val2 = getIIValue(xFloor+1, yFloor);
double val3 = getIIValue(xFloor , yFloor+1);
double val4 = getIIValue(xFloor+1, yFloor+1);
return blend2D(val, val2, val3, val4, x-xFloor, y-yFloor);
}
public int getIIValue(int x, int y) { return get(x, y); }
public double getIntegralValue(int x, int y, int channel) {
return get(x, y);
}
public double getPixelAverage(int x1, int y1, int x2, int y2) {
int area = (x2-x1)*(y2-y1);
return doubleRatio(bwIntegralImage_sumRect(this, x1, y1, x2, y2), area);
}
public int getWidth() { return w; }
public int getHeight() { return h; }
int packedToBrightness(int packed) {
int b = (packed & 0xFF);
int r = ((packed >> 16) & 0xFF);
int g = ((packed >> 8) & 0xFF);
return (r+g+b+1)/3;
}
// returns RGB pixel without alpha
public int getPixel(int x, int y) {
int r = iround(rectSum(x, y, x+1, y+1, 0));
int g = iround(rectSum(x, y, x+1, y+1, 1));
int b = iround(rectSum(x, y, x+1, y+1, 2));
return rgbInt(r, g, b);
}
public BufferedImage getBufferedImage() {
//ret scaleDownUsingIntegralImageBW(this, w).getBufferedImage();
Object src = metaGet("src", this);
if (src instanceof BufferedImage) return ((BufferedImage) src);
return grayImageFromIBWIntegralImage(this);
}
}
static interface IFieldsToList {
Object[] _fieldsToList();
}
static interface Decolorizer {
int toGrayScale(int rgb);
static class Red implements Decolorizer {
public int toGrayScale(int rgb) { return (rgb >> 16) & 0xFF; }
}
static class Green implements Decolorizer {
public int toGrayScale(int rgb) { return (rgb >> 8) & 0xFF; }
}
static class Blue implements Decolorizer {
public int toGrayScale(int rgb) { return rgb & 0xFF; }
}
static class Alpha implements Decolorizer {
public int toGrayScale(int rgb) { return (rgb >> 24) & 0xFF; }
}
// just the average of the 3 channels
static class Simple implements Decolorizer {
public int toGrayScale(int rgb) {
int r = (rgb >> 16) & 0xFF;
int g = (rgb >> 8) & 0xFF;
int b = rgb & 0xFF;
return (r+g+b+1)/3;
}
}
}
interface IHasTokenRangeWithSrc {
void setTokenRangeWithSrc(TokenRangeWithSrc src);
TokenRangeWithSrc tokenRangeWithSrc();
}
static class RGBImage implements MakesBufferedImage {
transient BufferedImage bufferedImage;
File file;
int width, height;
int[] pixels;
RGBImage() {}
RGBImage(BufferedImage image) {
this(image, null);
}
RGBImage(BufferedImage image, File file) {
this.file = file;
bufferedImage = image;
width = image.getWidth();
height = image.getHeight();
pixels = new int[width*height];
PixelGrabber pixelGrabber = new PixelGrabber(image, 0, 0, width, height, pixels, 0, width);
try {
if (!pixelGrabber.grabPixels())
throw new RuntimeException("Could not grab pixels");
cleanPixels(); // set upper byte to 0
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/** We assume it's a file name to load from */
RGBImage(String file) throws IOException {
this(new File(file));
}
RGBImage(Dimension size, Color color) {
this(size.width, size.height, color);
}
RGBImage(Dimension size, RGB color) {
this(size.width, size.height, color);
}
private void cleanPixels() {
for (int i = 0; i < pixels.length; i++)
pixels[i] &= 0xFFFFFF;
}
RGBImage(int width, int height, int[] pixels) {
this.width = width;
this.height = height;
this.pixels = pixels;
}
RGBImage(int w, int h, RGB[] pixels) {
this.width = w;
this.height = h;
this.pixels = asInts(pixels);
}
public static int[] asInts(RGB[] pixels) {
int[] ints = new int[pixels.length];
for (int i = 0; i < pixels.length; i++)
ints[i] = pixels[i] == null ? 0 : pixels[i].getColor().getRGB();
return ints;
}
public RGBImage(int w, int h) {
this(w, h, Color.black);
}
RGBImage(int w, int h, RGB rgb) {
this.width = w;
this.height = h;
this.pixels = new int[w*h];
int col = rgb.asInt();
if (col != 0)
for (int i = 0; i < pixels.length; i++)
pixels[i] = col;
}
RGBImage(RGBImage image) {
this(image.width, image.height, copyPixels(image.pixels));
}
RGBImage(int width, int height, Color color) {
this(width, height, new RGB(color));
}
RGBImage(File file) throws IOException {
this(javax.imageio.ImageIO.read(file));
}
RGBImage(MakesBufferedImage img) {
this(toBufferedImage(img));
}
private static int[] copyPixels(int[] pixels) {
int[] copy = new int[pixels.length];
System.arraycopy(pixels, 0, copy, 0, pixels.length);
return copy;
}
public int getIntPixel(int x, int y) {
if (inRange(x, y))
return pixels[y * width + x];
else
return 0xFFFFFF;
}
public static RGB asRGB(int packed) {
int r = (packed >> 16) & 0xFF;
int g = (packed >> 8) & 0xFF;
int b = packed & 0xFF;
return new RGB(r / 255f, g / 255f, b / 255f);
}
public RGB getRGB(int x, int y) {
if (inRange(x, y))
return asRGB(pixels[y * width + x]);
else
return new RGB(0xFFFFFF);
}
/** alias of getRGB - I kept typing getPixel instead of getRGB all the time, so I finally created it */
RGB getPixel(int x, int y) {
return getRGB(x, y);
}
RGB getPixel(Pt p) { return getPixel(p.x, p.y); }
public int getWidth() { return width; }
public int getHeight() { return height; }
int w() { return width; }
int h() { return height; }
/** Attention: cached, i.e. does not change when image itself changes */
/** @NotNull */
public BufferedImage getBufferedImage() {
if (bufferedImage == null) {
bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//bufferedImage.setData(Raster.createRaster(new SampleModel()));
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
bufferedImage.setRGB(x, y, pixels[y*width+x]);
}
return bufferedImage;
}
RGBImage clip(Rect r) {
return r == null ? null : clip(r.getRectangle());
}
RGBImage clip(Rectangle r) {
r = fixClipRect(r);
if (r.x == 0 && r.y == 0 && r.width == width && r.height == height) return this;
int[] newPixels;
try {
newPixels = new int[r.width*r.height];
} catch (RuntimeException e) {
System.out.println(r);
throw e;
}
for (int y = 0; y < r.height; y++) {
System.arraycopy(pixels, (y+r.y)*width+r.x, newPixels, y*r.width, r.width);
}
return new RGBImage(r.width, r.height, newPixels);
}
private Rectangle fixClipRect(Rectangle r) {
r = r.intersection(new Rectangle(0, 0, width, height));
if (r.isEmpty())
r = new Rectangle(r.x, r.y, 0, 0);
return r;
}
public File getFile() {
return file;
}
/** can now also do GIF (not just JPEG) */
public static RGBImage load(String fileName) {
return load(new File(fileName));
}
/** can now also do GIF (not just JPEG) */
public static RGBImage load(File file) {
try {
BufferedImage bufferedImage = javax.imageio.ImageIO.read(file);
return new RGBImage(bufferedImage);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public int getInt(int x, int y) {
return pixels[y * width + x];
}
public void save(File file) throws IOException {
String name = file.getName().toLowerCase();
String type;
if (name.endsWith(".png")) type = "png";
else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) type = "jpeg";
else throw new IOException("Unknown image extension: " + name);
javax.imageio.ImageIO.write(getBufferedImage(), type, file);
}
public static RGBImage dummyImage() {
return new RGBImage(1, 1, new int[] {0xFFFFFF});
}
public int[] getPixels() {
return pixels;
}
void setPixel(int x, int y, int r, int g, int b) {
if (x >= 0 && y >= 0 && x < width && y < height)
pixels[y*width+x] = (limitToUByte(r) << 16) | (limitToUByte(g) << 8) | limitToUByte(b);
}
public void setPixel(int x, int y, RGB rgb) {
if (x >= 0 && y >= 0 && x < width && y < height)
pixels[y*width+x] = rgb.asInt();
}
final public void set(int x, int y, Color color){ setPixel(x, y, color); }
public void setPixel(int x, int y, Color color) {
setPixel(x, y, new RGB(color));
}
void setInt(int x, int y, int rgb) {
setPixel(x, y, rgb);
}
public void setPixel(int x, int y, int rgb) {
if (x >= 0 && y >= 0 && x < width && y < height)
pixels[y*width+x] = rgb;
}
void setPixel(Pt p, RGB rgb) { setPixel(p.x, p.y, rgb); }
void setPixel(Pt p, Color color) { setPixel(p.x, p.y, color); }
public RGBImage copy() {
return new RGBImage(this);
}
public boolean inRange(int x, int y) {
return x >= 0 && y >= 0 && x < width && y < height;
}
public Dimension getSize() {
return new Dimension(width, height);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RGBImage rgbImage = (RGBImage) o;
if (height != rgbImage.height) return false;
if (width != rgbImage.width) return false;
if (!Arrays.equals(pixels, rgbImage.pixels)) return false;
return true;
}
@Override
public int hashCode() {
int result = width;
result = 31 * result + height;
result = 31 * result + Arrays.hashCode(pixels);
return result;
}
public String getHex(int x, int y) {
return getPixel(x, y).getHexString();
}
public RGBImage clip(int x, int y, int width, int height) {
return clip(new Rectangle(x, y, width, height));
}
public RGBImage clipLine(int y) {
return clip(0, y, width, 1);
}
public int numPixels() {
return width*height;
}
void uncacheBufferedImage() {
bufferedImage = null;
}
}
static interface WidthAndHeight {
int getWidth();
int getHeight();
public default Rect bounds() { return rect(0, 0, getWidth(), getHeight()); }
}
static class SynchronizedList
extends SynchronizedCollection
implements List {
SynchronizedList() {}
/*final*/ List list;
SynchronizedList(List list) {
super(list);
this.list = list;
}
SynchronizedList(List list, Object mutex) {
super(list, mutex);
this.list = list;
}
public boolean equals(Object o) {
if (this == o)
return true;
synchronized (mutex) {return list.equals(o);}
}
public int hashCode() {
synchronized (mutex) {return list.hashCode();}
}
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
public E set(int index, E element) {
synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {
synchronized (mutex) {return list.remove(index);}
}
public int indexOf(Object o) {
synchronized (mutex) {return list.indexOf(o);}
}
public int lastIndexOf(Object o) {
synchronized (mutex) {return list.lastIndexOf(o);}
}
public boolean addAll(int index, Collection extends E> c) {
synchronized (mutex) {return list.addAll(index, c);}
}
public ListIterator listIterator() {
return list.listIterator(); // Must be manually synched by user
}
public ListIterator listIterator(int index) {
return list.listIterator(index); // Must be manually synched by user
}
public List subList(int fromIndex, int toIndex) {
synchronized (mutex) {
return new SynchronizedList<>(list.subList(fromIndex, toIndex),
mutex);
}
}
@Override
public void replaceAll(java.util.function.UnaryOperator operator) {
synchronized (mutex) {list.replaceAll(operator);}
}
@Override
public void sort(Comparator super E> c) {
synchronized (mutex) {list.sort(c);}
}
/**
* SynchronizedRandomAccessList instances are serialized as
* SynchronizedList instances to allow them to be deserialized
* in pre-1.4 JREs (which do not have SynchronizedRandomAccessList).
* This method inverts the transformation. As a beneficial
* side-effect, it also grafts the RandomAccess marker onto
* SynchronizedList instances that were serialized in pre-1.4 JREs.
*
* Note: Unfortunately, SynchronizedRandomAccessList instances
* serialized in 1.4.1 and deserialized in 1.4 will become
* SynchronizedList instances, as this method was missing in 1.4.
*/
@java.io.Serial
private Object readResolve() {
return (list instanceof RandomAccess
? new SynchronizedRandomAccessList<>(list)
: this);
}
}
static class FastRegions_BWImage implements Runnable, IImageRegions , IFieldsToList{
BWImage image;
FastRegions_BWImage() {}
FastRegions_BWImage(BWImage image) {
this.image = image;}public Object[] _fieldsToList() { return new Object[] {image}; }
int w, h, runner;
final public int getSize(){ return size(); }
public int size() { return size; } int size;
IntBuffer stack = new IntBuffer(); // locations as y*w+x
int[] regionMatrix; // for each pixel: region index (starting at 1)
IntBuffer regionPixels = new IntBuffer(); // collect all pixels for regions
// initialize these to use them
IntBuffer regionFirstPixel = new IntBuffer(); // for each region: index of first pixel found in regionPixels
IntBuffer regionSize = new IntBuffer(); // for each region: number of pixels
IntBuffer regionBounds = new IntBuffer(); // for each region: bounds (x1, y1, x2, y2)
// index = dual log of region size, value = region index
List regionsBySize = new ArrayList();
int regionCounter;
boolean verbose = false;
double regionStep = .1; // for rendering in regionsImage
int x(int pos) { return pos % w; }
int y(int pos) { return pos / w; }
int pos(int x, int y) { return y*w+x; }
Pt pt(int pos) { return new Pt(x(pos), y(pos)); }
boolean validPos(int x, int y) { return x >= 0 && y >= 0 && x < w && y < h; }
int getColor(int pos) { return image.getInt(x(pos), y(pos)); }
FastRegions_BWImage(BufferedImage img) { this(toBWImage(img)); }
public void run() { try {
w = image.getWidth(); h = image.getHeight();
size = w*h;
regionMatrix = new int[size];
// 0 entries are unused
{ if (regionFirstPixel != null) regionFirstPixel.add(0); }
{ if (regionSize != null) regionSize.add(0); }
{ if (regionPixels != null) regionPixels.setSize(size); }
while (runner < size) {
if (regionMatrix[runner] == 0) {
// make a new region, get color
int region = ++regionCounter;
{ if (regionFirstPixel != null) regionFirstPixel.add(regionPixels != null ? l(regionPixels) : runner); }
stack.add(runner);
int color = getColor(runner);
int rsize = 0, x1 = w, y1 = h, x2 = 0, y2 = 0;
// flood-fill region
while (nempty(stack)) {
int pos = stack.popLast();
if (regionMatrix[pos] != 0) continue; // touching myself (or someone else)
if (getColor(pos) != color) continue; // wrong color
// new pixel found, mark as ours
regionMatrix[pos] = region;
++rsize;
{ if (regionPixels != null) regionPixels.add(pos); }
int x = x(pos), y = y(pos);
if (x < x1) x1 = x;
if (x > x2) x2 = x;
if (y < y1) y1 = y;
if (y > y2) y2 = y;
// explore neighborhood
if (x > 0) stack.add(pos-1);
if (x < w-1) stack.add(pos+1);
if (y > 0) stack.add(pos-w);
if (y < h-1) stack.add(pos+w);
}
{ if (regionSize != null) regionSize.add(rsize); }
{ if (regionBounds != null) regionBounds.addAll(x1, y1, x2+1, y2+1); }
if (regionsBySize != null) {
int iBucket = dualLog(rsize);
var buffer = listGetOrCreate(regionsBySize, iBucket, () -> new IntBuffer());
buffer.add(region);
}
}
++runner;
}
} catch (Exception __e) { throw rethrow(__e); } }
IBWImage regionsImage() {
return iBWImageFromFunction((x, y) -> {
var region = regionMatrix[pos(x, y)];
return ((region-1)*regionStep) % (1.0+regionStep-0.0001);
}, w, h);
}
final int nRegions(){ return regionCount(); }
int regionCount() { return regionCounter; }
abstract class RegionIterator {
int pos;
abstract boolean next();
int pos() { return pos; }
int x() { return FastRegions_BWImage.this.x(pos); }
int y() { return FastRegions_BWImage.this.y(pos); }
}
// returns points in no particular order
class FloodRegionIterator extends RegionIterator {
int region;
IntBuffer stack = new IntBuffer(); // locations as y*w+x
BitSet seen = new BitSet(size);
FloodRegionIterator(int region) {
this.region = region;
int pos = regionFirstPixel.get(region);
printVars("region", region, "pos", pos);
seen.set(pos);
stack.add(pos);
}
// flood-fill region
boolean next() {
if (empty(stack)) return false;
pos = stack.popLast();
// explore neighborhood
int x = x(), y = y();
if (x > 0) tryPosition(pos-1);
if (x < w-1) tryPosition(pos+1);
if (y > 0) tryPosition(pos-w);
if (y < h-1) tryPosition(pos+w);
return true;
}
private void tryPosition(int p) {
if (!seen.get(p) && regionMatrix[p] == region) {
seen.set(p);
stack.add(p);
}
}
}
class CachedRegionIterator extends RegionIterator {
int i, to;
CachedRegionIterator(int region) {
i = regionFirstPixel.get(region);
to = region+1 < l(regionFirstPixel) ? regionFirstPixel.get(region+1) : l(regionPixels);
}
boolean next() {
if (i >= to) return false;
pos = regionPixels.get(i++);
return true;
}
}
int regionSize(int iRegion) { return regionSize.get(iRegion); }
final Pt firstPixel(int iRegion){ return samplePixel(iRegion); }
Pt samplePixel(int iRegion) {
return pt(firstPixelPos(iRegion));
}
int firstPixelPos(int iRegion) {
int i = regionFirstPixel.get(iRegion);
return regionPixels != null ? regionPixels.get(i) : i;
}
boolean inRegion(int iRegion, int x, int y) {
return validPos(x, y) && regionMatrix[pos(x, y)] == iRegion;
}
Rect regionBounds(int iRegion) { return rectFromPoints(
regionBounds.get((iRegion-1)*4),
regionBounds.get((iRegion-1)*4+1),
regionBounds.get((iRegion-1)*4+2),
regionBounds.get((iRegion-1)*4+3)); }
int regionAt(Pt p) { return regionAt(p.x, p.y); }
int regionAt(int x, int y) {
return !validPos(x, y) ? 0 : regionMatrix[pos(x, y)];
}
int regionAt(int pos) {
return regionMatrix[pos];
}
RegionIterator regionIterator(int iRegion) {
return regionPixels != null
? new CachedRegionIterator(iRegion)
: new FloodRegionIterator(iRegion);
}
List regionPixels(int iRegion) {
var it = regionIterator(iRegion);
List l = new ArrayList();
while (it.next())
l.add(new Pt(it.x(), it.y()));
return l;
}
// select extra features before regions are made
// (not necessary anymore)
void collectFirstPixels() { /*regionFirstPixel = new IntBuffer;*/ }
void collectBounds() { /*regionBounds = new IntBuffer;*/ }
Matrix regionBitMatrix(int iRegion) {
return new AbstractMatrix(w, h) {
public Boolean get(int x, int y) {
return inRegion(iRegion, x, y);
}
};
}
void markRegionInPixelArray(int[] pixels, int iRegion, int rgba) {
if (iRegion <= 0) return;
for (int i = 0; i < l(pixels); i++)
if (regionAt(i) == iRegion)
pixels[i] = rgba;
}
List regionIndices() { return virtualCountList(1, nRegions()+1); }
IterableIterator regionsRoughlyByDecreasingSize() {
return nestedIterator(countIterator_inclusive_backwards(regionsBySize.size()-1, 0),
iBucket -> iterator(regionsBySize.get(iBucket)));
}
final IImageRegion get(int iRegion){ return getRegion(iRegion); }
IImageRegion getRegion(int iRegion) {
return new ImageRegion(iRegion);
}
public List> regions() {
return listFromFunction(i -> getRegion(i+1), nRegions());
}
class ImageRegion implements IImageRegion , IFieldsToList{
int iRegion;
ImageRegion() {}
ImageRegion(int iRegion) {
this.iRegion = iRegion;}
public boolean equals(Object o) {
if (!(o instanceof ImageRegion)) return false;
ImageRegion __0 = (ImageRegion) o;
return iRegion == __0.iRegion;
}
public int hashCode() {
int h = -494554097;
h = boostHashCombine(h, _hashCode(iRegion));
return h;
}
public Object[] _fieldsToList() { return new Object[] {iRegion}; }
public BWImage image() { return image; }
public Object creator() { return FastRegions_BWImage.this; }
public int indexInCreator() { return iRegion; }
public Rect bounds() { return regionBounds(iRegion); }
public int numberOfPixels() { return regionSize(iRegion); }
public Pt firstPixel() { return pt(firstPixelPos()); }
public int firstPixelPos() { return FastRegions_BWImage.this.firstPixelPos(iRegion); }
public Iterator pixelIterator() {
var it = regionIterator(iRegion);
return iteratorFromFunction(() -> it.next() ? pt(it.pos()) : null);
}
public boolean contains(int x, int y) { return inRegion(iRegion, x, y); }
public RGB color() {
return rgbFromGrayscale(brightness());
}
public int brightness() {
return getColor(firstPixelPos());
}
public String toString() {
return renderRecordVars("Region", "brightness", brightness(), "color", color(), "pixels" , numberOfPixels(), "bounds", bounds());
}
}
}
static class GrabbableGrayPixels implements IFieldsToList{
static final String _fieldOrder = "data w h offset scanlineStride";
byte[] data;
int w;
int h;
int offset;
int scanlineStride;
GrabbableGrayPixels() {}
GrabbableGrayPixels(byte[] data, int w, int h, int offset, int scanlineStride) {
this.scanlineStride = scanlineStride;
this.offset = offset;
this.h = h;
this.w = w;
this.data = data;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + data + ", " + w + ", " + h + ", " + offset + ", " + scanlineStride + ")"; }
public boolean equals(Object o) {
if (!(o instanceof GrabbableGrayPixels)) return false;
GrabbableGrayPixels __1 = (GrabbableGrayPixels) o;
return eq(data, __1.data) && w == __1.w && h == __1.h && offset == __1.offset && scanlineStride == __1.scanlineStride;
}
public int hashCode() {
int h = 1984426208;
h = boostHashCombine(h, _hashCode(data));
h = boostHashCombine(h, _hashCode(w));
h = boostHashCombine(h, _hashCode(h));
h = boostHashCombine(h, _hashCode(offset));
h = boostHashCombine(h, _hashCode(scanlineStride));
return h;
}
public Object[] _fieldsToList() { return new Object[] {data, w, h, offset, scanlineStride}; }
}
static interface IMeta {
// see class "Meta" for the bla bla
public void _setMeta(Object meta);
public Object _getMeta();
default public IAutoCloseableF0 _tempMetaMutex() {
return new IAutoCloseableF0() {
public Object get() { return IMeta.this; }
public void close() {}
};
}
// actually query another object
default public Object getMeta(Object obj, Object key){ return metaGet(obj, key); }
default public Object metaGet(Object obj, Object key) {
// call global function
return metaMapGet(obj, key);
}
default public Object metaGet(String key, Object obj) {
// call global function
return metaMapGet(obj, key);
}
default public Object getMeta(Object key){ return metaGet(key); }
default public Object metaGet(Object key) {
if (key == null) return null;
Object meta = _getMeta();
if (meta instanceof Map) return ((Map) meta).get(key);
return null;
}
default public void metaSet(IMeta obj, Object key, Object value){ metaPut(obj, key, value); }
default public void metaPut(IMeta obj, Object key, Object value) {
// call global function
metaMapPut(obj, key, value);
}
default public void metaSet(Object key, Object value){ metaPut(key, value); }
default public void metaPut(Object key, Object value) {
if (key == null) return;
Map map = convertObjectMetaToMap(this);
syncMapPutOrRemove(map, key, value);
}
}
static class Average {
double sum, n;
void add(double d) {
++n;
sum += d;
}
void add(double d, double weight) {
n += weight;
sum += d*weight;
}
double get() {
return doubleRatio(sum, n);
}
double n() { return n; }
public String toString() { return get() + " (n=" + n + ")"; }
void clear() {
n = 0;
sum = 0;
}
}
// Both lines and columns are numbered from 1
static class LineAndColumn {
int line, col;
LineAndColumn(int line, int col) {
this.col = col;
this.line = line;}
// get text of a line. may return null if no text available
transient IF1 getLineText;
String getLineText(int line) { return getLineText != null ? getLineText.get(line) : getLineText_base(line); }
final String getLineText_fallback(IF1 _f, int line) { return _f != null ? _f.get(line) : getLineText_base(line); }
String getLineText_base(int line) { return null; }
public String toString() { return "Line " + n2(line) + ", col " + n2(col); }
}
static class TimestampRange implements IFieldsToList{
static final String _fieldOrder = "start end";
Timestamp start;
Timestamp end;
TimestampRange() {}
TimestampRange(Timestamp start, Timestamp end) {
this.end = end;
this.start = start;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + start + ", " + end + ")"; }
public boolean equals(Object o) {
if (!(o instanceof TimestampRange)) return false;
TimestampRange __1 = (TimestampRange) o;
return eq(start, __1.start) && eq(end, __1.end);
}
public int hashCode() {
int h = -2020922905;
h = boostHashCombine(h, _hashCode(start));
h = boostHashCombine(h, _hashCode(end));
return h;
}
public Object[] _fieldsToList() { return new Object[] {start, end}; }
TimestampRange(long start, long end) {
this(new Timestamp(start), new Timestamp(end));
}
TimestampRange start(Timestamp start) { this.start = start; return this; }
TimestampRange end(Timestamp end) { this.end = end; return this; }
}
static class GrabbableIntPixels implements IFieldsToList{
static final String _fieldOrder = "data w h offset scanlineStride";
int[] data;
int w;
int h;
int offset;
int scanlineStride;
GrabbableIntPixels() {}
GrabbableIntPixels(int[] data, int w, int h, int offset, int scanlineStride) {
this.scanlineStride = scanlineStride;
this.offset = offset;
this.h = h;
this.w = w;
this.data = data;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + data + ", " + w + ", " + h + ", " + offset + ", " + scanlineStride + ")"; }
public boolean equals(Object o) {
if (!(o instanceof GrabbableIntPixels)) return false;
GrabbableIntPixels __1 = (GrabbableIntPixels) o;
return eq(data, __1.data) && w == __1.w && h == __1.h && offset == __1.offset && scanlineStride == __1.scanlineStride;
}
public int hashCode() {
int h = -1183022196;
h = boostHashCombine(h, _hashCode(data));
h = boostHashCombine(h, _hashCode(w));
h = boostHashCombine(h, _hashCode(h));
h = boostHashCombine(h, _hashCode(offset));
h = boostHashCombine(h, _hashCode(scanlineStride));
return h;
}
public Object[] _fieldsToList() { return new Object[] {data, w, h, offset, scanlineStride}; }
}
static interface IBWIntegralImage extends MakesBufferedImage, IBWImage, IMeta {
public int getWidth();
public int getHeight();
// implement one of the following two methods!
// integer version (both coordinates & brightnesses are ints)
public default int getIIValue(int x, int y) {
return iround(getIIValue((double) x, (double) y));
}
// floating point version (both coordinates & brightnesses are doubles)
public default double getIIValue(double x, double y) {
return getIIValue(ifloor(x), ifloor(y));
}
// 0.0 to 255.0
default public double getPixelAverage(int x1, int y1, int x2, int y2) {
int area = (x2-x1)*(y2-y1);
return doubleRatio(getPixelSum(x1, y1, x2, y2), area);
}
default public double getPixelAverage(double x1, double y1, double x2, double y2) {
double area = (x2-x1)*(y2-y1);
return doubleRatio(getPixelSum(x1, y1, x2, y2), area);
}
default public double getPixelAverage(Rect r) {
return getPixelAverage(r.x, r.y, r.x2(), r.y2());
}
default public int getPixelSum(int x1, int y1, int x2, int y2) {
return bwIntegralImage_sumRect(this, x1, y1, x2, y2);
}
default public double getPixelSum(double x1, double y1, double x2, double y2) {
return bwIntegralImage_sumRect(this, x1, y1, x2, y2);
}
default public int getPixelBrightness(int x, int y) {
return getPixelSum(x, y, x+1, y+1);
}
default public int getPixelBrightness(Pt p) { return getPixelBrightness(p.x, p.y); }
public default BufferedImage getBufferedImage() {
//ret scaleDownUsingIntegralImageBW(this, w).getBufferedImage();
return grayImageFromIBWIntegralImage(this);
}
// implementing IBWImage
public default float getFloatPixel(int x, int y) {
return getPixelBrightness(x, y)/255f;
}
}
static class SynchronizedRandomAccessList
extends SynchronizedList
implements RandomAccess {
SynchronizedRandomAccessList() {}
SynchronizedRandomAccessList(List list) {
super(list);
}
SynchronizedRandomAccessList(List list, Object mutex) {
super(list, mutex);
}
public List subList(int fromIndex, int toIndex) {
synchronized (mutex) {
return new SynchronizedRandomAccessList<>(
list.subList(fromIndex, toIndex), mutex);
}
}
@java.io.Serial
private static final long serialVersionUID = 1530674583602358482L;
/**
* Allows instances to be deserialized in pre-1.4 JREs (which do
* not have SynchronizedRandomAccessList). SynchronizedList has
* a readResolve method that inverts this transformation upon
* deserialization.
*/
@java.io.Serial
private Object writeReplace() {
return new SynchronizedList<>(list);
}
}
static class SynchronizedCollection implements Collection, Serializable {
SynchronizedCollection() {}
@java.io.Serial
private static final long serialVersionUID = 3053995032091335093L;
@SuppressWarnings("serial") // Conditionally serializable
/*final*/ Collection c; // Backing Collection
@SuppressWarnings("serial") // Conditionally serializable
/*final*/ Object mutex; // Object on which to synchronize
SynchronizedCollection(Collection c) {
this.c = Objects.requireNonNull(c);
mutex = this;
}
SynchronizedCollection(Collection c, Object mutex) {
this.c = Objects.requireNonNull(c);
this.mutex = Objects.requireNonNull(mutex);
}
public int size() {
synchronized (mutex) {return c.size();}
}
public boolean isEmpty() {
synchronized (mutex) {return c.isEmpty();}
}
public boolean contains(Object o) {
synchronized (mutex) {return c.contains(o);}
}
public Object[] toArray() {
synchronized (mutex) {return c.toArray();}
}
public T[] toArray(T[] a) {
synchronized (mutex) {return c.toArray(a);}
}
public T[] toArray(java.util.function.IntFunction f) {
synchronized (mutex) {return c.toArray(f);}
}
public Iterator iterator() {
return c.iterator(); // Must be manually synched by user!
}
public boolean add(E e) {
synchronized (mutex) {return c.add(e);}
}
public boolean remove(Object o) {
synchronized (mutex) {return c.remove(o);}
}
public boolean containsAll(Collection> coll) {
synchronized (mutex) {return c.containsAll(coll);}
}
public boolean addAll(Collection extends E> coll) {
synchronized (mutex) {return c.addAll(coll);}
}
public boolean removeAll(Collection> coll) {
synchronized (mutex) {return c.removeAll(coll);}
}
public boolean retainAll(Collection> coll) {
synchronized (mutex) {return c.retainAll(coll);}
}
public void clear() {
synchronized (mutex) {c.clear();}
}
public String toString() {
synchronized (mutex) {return c.toString();}
}
// Override default methods in Collection
@Override
public void forEach(java.util.function.Consumer super E> consumer) {
synchronized (mutex) {c.forEach(consumer);}
}
@Override
public boolean removeIf(java.util.function.Predicate super E> filter) {
synchronized (mutex) {return c.removeIf(filter);}
}
@Override
public Spliterator spliterator() {
return c.spliterator(); // Must be manually synched by user!
}
@Override
public java.util.stream.Stream stream() {
return c.stream(); // Must be manually synched by user!
}
@Override
public java.util.stream.Stream parallelStream() {
return c.parallelStream(); // Must be manually synched by user!
}
@java.io.Serial
private void writeObject(ObjectOutputStream s) throws IOException {
synchronized (mutex) {s.defaultWriteObject();}
}
}
static class ListAndIndex implements IFieldsToList{
static final String _fieldOrder = "list idx";
List list;
int idx;
ListAndIndex() {}
ListAndIndex(List list, int idx) {
this.idx = idx;
this.list = list;}
public boolean equals(Object o) {
if (!(o instanceof ListAndIndex)) return false;
ListAndIndex __1 = (ListAndIndex) o;
return eq(list, __1.list) && idx == __1.idx;
}
public int hashCode() {
int h = 276903961;
h = boostHashCombine(h, _hashCode(list));
h = boostHashCombine(h, _hashCode(idx));
return h;
}
public Object[] _fieldsToList() { return new Object[] {list, idx}; }
boolean atEnd() { return idx >= l(list); }
A get() { return _get(list, idx); }
int size() { return l(list); }
public String toString() {
return subList(list, 0, idx) + ", then " + subList(list, idx);
}
ListAndIndex plus(int ofs) { return new ListAndIndex(list, idx+ofs); }
List list() { return list; }
final int idx(){ return index(); }
int index() { return idx; }
}
static class TokenRange extends IntRange {
TokenRange() {}
TokenRange(int start, int end) {
this.end = end;
this.start = start;}
}
interface IDoublePt {
public double x_double();
public double y_double();
}
static class VarMatches extends WrappedMap {
VarMatches() { super(new LinkedHashMap()); }
VarMatches(Map map) { this(); main.putAll(this, map); }
}
static interface IIntegralImage extends MakesBufferedImage {
public int getWidth();
public int getHeight();
default public Pt getSize() { return pt(getWidth(), getHeight()); }
default public int defaultChannel() { return 0; }
default public int nChannels() { return 3; }
// get value for 1 channel
// normal range [0; pixelCount*256)
public double getIntegralValue(int x, int y, int channel);
default double getIntegralValue(double x, double y, int channel) {
return getIntegralValue(ifloor(x), ifloor(y), channel);
}
// gets summed value of the 3 channels
// normal range [0; pixelCount*256*3)
default double getIntegralValue(int x, int y) {
return getIntegralValue(x, y, 0)
+ getIntegralValue(x, y, 1)
+ getIntegralValue(x, y, 2);
}
default double rectSum(int x1, int y1, int x2, int y2, int channel) {
double bottomLeft = getIntegralValue(x1-1, y2-1, channel);
double bottomRight = getIntegralValue(x2-1, y2-1, channel);
double topLeft = getIntegralValue(x1-1, y1-1, channel);
double topRight = getIntegralValue(x2-1, y1-1, channel);
return bottomRight+topLeft-topRight-bottomLeft;
}
default double rectSum(double x1, double y1, double x2, double y2, int channel) {
return rectSum(iround(x1), iround(y1), iround(x2), iround(y2), channel);
}
default double rectSum(int x1, int y1, int x2, int y2) {
double bottomLeft = getIntegralValue(x1-1, y2-1);
double bottomRight = getIntegralValue(x2-1, y2-1);
double topLeft = getIntegralValue(x1-1, y1-1);
double topRight = getIntegralValue(x2-1, y1-1);
return bottomRight+topLeft-topRight-bottomLeft;
}
default double rectAverage(int x1, int y1, int x2, int y2, int channel) {
return doubleRatio(rectSum(x1, y1, x2, y2, channel), areaFromPoints(x1, y1, x2, y2));
}
default double rectAverage(Rect r, int channel) {
return doubleRatio(rectSum(r, channel), rectArea(r));
}
default double rectSum(Rect r) {
return rectSum(r.x, r.y, r.x2(), r.y2());
}
default double rectSum(Rect r, int channel) {
return rectSum(r.x, r.y, r.x2(), r.y2(), channel);
}
default double pixelSum(DoubleRect r) {
return rectSum(toRect_floor(r), defaultChannel());
}
default IIntegralImage clip(int x, int y, int w, int h) {
return new IIVirtualClip(this, x, y, w, h);
}
default double averageBrightness() {
int w = getWidth(), h = getHeight();
return doubleRatio(getIntegralValue(w-1, h-1), w*h*3*255.0);
}
default RGB averageRGB() {
int w = getWidth(), h = getHeight();
double factor = 1/(255.0*(w*h));
return new RGB(
rectSum(0, 0, w, h, 0)*factor,
rectSum(0, 0, w, h, 1)*factor,
rectSum(0, 0, w, h, 2)*factor);
}
// normal range: (0, 255)
default double getPixel(int x, int y, int channel) {
return rectSum(x, y, x+1, y+1, channel);
}
// returns RGB pixel without alpha
default int getPixel(int x, int y) {
int r = iround(rectSum(x, y, x+1, y+1, 0));
int g = iround(rectSum(x, y, x+1, y+1, 1));
int b = iround(rectSum(x, y, x+1, y+1, 2));
return rgbInt(r, g, b);
}
default int nPixels() { return getWidth()*getHeight(); }
default BufferedImage getBufferedImage() {
int w = getWidth(), h = getHeight();
int[] pixels = new int[w*h];
int i = 0;
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
pixels[i++] = getPixel(x, y) | fullAlphaMask();
return intArrayToBufferedImage(pixels, w, h);
}
// minimum and maximum brightness possible in image
// Better not to use because without this information
// you have a more general recognition algorithm.
//default DoubleRange colorRange(int channel) { ret doubleRange(0, 256); }
}
interface IImageRegions {
public List> regions();
}
static class IIVirtualClip extends Meta implements IIntegralImage {
RegisteredReference < IIntegralImage > fullImage = new RegisteredReference<>(this);
int x1, y1, w, h;
IIVirtualClip() {}
IIVirtualClip(IIntegralImage fullImage, int x1, int y1, int w, int h) {
this.fullImage.set(fullImage);
this.h = h;
this.w = w;
this.y1 = y1;
this.x1 = x1;
}
public int getWidth() { return w; }
public int getHeight() { return h; }
public double getIntegralValue(int x, int y, int channel) {
return fullImage.get().getIntegralValue(x+x1, y+y1, channel);
}
public double getIntegralValue(int x, int y) {
return fullImage.get().getIntegralValue(x+x1, y+y1);
}
public BufferedImage getBufferedImage() {
return clipBufferedImage(fullImage.get().getBufferedImage(), x1, y1, w, h);
}
}
static class WrappedMap extends AbstractMap {
Map map;
WrappedMap() {}
WrappedMap(Map map) {
this.map = map;}
public B get(Object key) {
return map.get(key);
}
public B put(A key, B value) {
return map.put(key, value);
}
public boolean containsKey(Object key) {
return map.containsKey(key);
}
public Set> entrySet() {
return map.entrySet();
}
}
static class IntBuffer implements Iterable {
int[] data;
int size;
IntBuffer() {}
IntBuffer(int size) { if (size != 0) data = new int[size]; }
IntBuffer(Iterable l) { this(l(l)); addAll(l); }
void add(int i) {
if (size >= lIntArray(data)) {
data = resizeIntArray(data, Math.max(1, toInt(Math.min(maximumSafeArraySize(), lIntArray(data)*2L))));
if (size >= data.length) throw fail("IntBuffer too large: " + size);
}
data[size++] = i;
}
void setSize(int n) {
data = resizeIntArray(data, n);
size = min(l(data), size);
}
void addAll(Iterable l) {
if (l != null) for (int i : l) add(i);
}
void addAll(int... l) {
if (l != null) for (int i : l) add(i);
}
// Note: may return the internal array
final int[] toIntArray(){ return toArray(); }
int[] toArray() {
return size == 0 ? null : resizeIntArray(data, size);
}
List toList() {
return intArrayToList(data, 0, size);
}
List asVirtualList() {
return new RandomAccessAbstractList() {
public int size() { return size; }
public Integer get(int i) { return IntBuffer.this.get(i); }
public Integer set(int i, Integer val) {
Integer a = get(i);
data[i] = val;
return a;
}
};
}
void reset() { size = 0; }
void clear() { reset(); }
int size() { return size; }
boolean isEmpty() { return size == 0; }
int get(int idx) {
if (idx >= size) throw fail("Index out of range: " + idx + "/" + size);
return data[idx];
}
void set(int idx, int value) {
if (idx >= size) throw fail("Index out of range: " + idx + "/" + size);
data[idx] = value;
}
int popLast() {
if (size == 0) throw fail("empty buffer");
return data[--size];
}
int last() { return data[size-1]; }
int nextToLast() { return data[size-2]; }
public String toString() { return squareBracket(joinWithSpace(toList())); }
public Iterator iterator() {
return new IterableIterator() {
int i = 0;
public boolean hasNext() { return i < size; }
public Integer next() {
//if (!hasNext()) fail("Index out of bounds: " + i);
return data[i++];
}
};
}
public IntegerIterator integerIterator() {
return new IntegerIterator() {
int i = 0;
public boolean hasNext() { return i < size; }
public int next() {
//if (!hasNext()) fail("Index out of bounds: " + i);
return data[i++];
}
public String toString() { return "Iterator@" + i + " over " + IntBuffer.this; }
};
}
void trimToSize() {
data = resizeIntArray(data, size);
}
}
// it's unclear whether the end is inclusive or exclusive
// (usually exclusive I guess)
static class IntRange {
int start, end;
IntRange() {}
IntRange(int start, int end) {
this.end = end;
this.start = start;}
IntRange(IntRange r) { start = r.start; end = r.end; }
public boolean equals(Object o) { return stdEq2(this, o); }
public int hashCode() { return stdHash2(this); }
final int length() { return end-start; }
final boolean empty() { return start >= end; }
final boolean isEmpty() { return start >= end; }
static String _fieldOrder = "start end";
public String toString() { return "[" + start + ";" + end + "]"; }
}
static interface IAutoCloseableF0 extends IF0 , AutoCloseable {}
static class Timestamp implements Comparable , IFieldsToList{
long date;
Timestamp(long date) {
this.date = date;}
public boolean equals(Object o) {
if (!(o instanceof Timestamp)) return false;
Timestamp __1 = (Timestamp) o;
return date == __1.date;
}
public int hashCode() {
int h = 2059094262;
h = boostHashCombine(h, _hashCode(date));
return h;
}
public Object[] _fieldsToList() { return new Object[] {date}; }
Timestamp() { date = now(); }
long unixDate() { return date; }
public String toString() { return formatLocalDateWithSeconds(date); }
// Hmm. Should Timestamp(0) be equal to null? Question, questions...
public int compareTo(Timestamp t) {
return t == null ? 1 : cmp(date, t.date);
}
Timestamp plus(Seconds seconds) {
return plus(seconds == null ? null : seconds.getDouble());
}
final Timestamp plusSeconds(double seconds){ return plus(seconds); }
Timestamp plus(double seconds) {
return new Timestamp(date+toMS(seconds));
}
// returns milliseconds
long minus(Timestamp ts) {
return unixDate()-ts.unixDate();
}
long sysTime() {
return clockTimeToSystemTime(date);
}
}
static class DoubleRect {
double x, y, w, h;
DoubleRect() {}
DoubleRect(Rectangle r) {
x = r.x;
y = r.y;
w = r.width;
h = r.height;
}
DoubleRect(double x, double y, double w, double h) {
this.h = h;
this.w = w;
this.y = y;
this.x = x;}
// Huh. not implementing equals()/hashCode? Stefan is mysterious
boolean eq(Object o) {
if (!(o instanceof DoubleRect)) return false;
if (o == this) return true;
DoubleRect r = (DoubleRect) o;
return x == r.x && y == r.y && w == r.w && h == r.h;
}
public String toString() {
return x + "," + y + " / " + w + "," + h;
}
double x1() { return x; }
double y1() { return y; }
double x2() { return x + w; }
double y2() { return y + h; }
boolean contains(Pt p) {
return contains(p.x, p.y);
}
boolean contains(double _x, double _y) {
return _x >= x && _y >= y && _x < x+w && _y < y+h;
}
boolean empty() { return w <= 0 || h <= 0; }
}
abstract static class AbstractMatrix implements Matrix {
AbstractMatrix() {}
int w, h;
AbstractMatrix(int w, int h) {
this.h = h;
this.w = w;}
public int getWidth() { return w; }
public int getHeight() { return h; }
public String toString() {
return flexLines(
roundBracket(w+"x"+h),
countIteratorToList(y -> str(getLine(y)), getHeight()));
}
public void set(int x, int y, A a) { unimplemented(); }
}
interface Matrix extends WidthAndHeight {
public A get(int x, int y);
public void set(int x, int y, A a);
default Pt size() { return pt(getWidth(), getHeight()); }
default int nCells() { return getWidth()*getHeight(); }
default A get(Pt p) { return get(p.x, p.y); }
default void put(Pt p, A a){ set(p, a); }
default void set(Pt p, A a) { set(p.x, p.y, a); }
default List getLine(int y) {
return new RandomAccessAbstractList () {
public int size() { return getWidth(); }
public A get(int x) {
return Matrix.this.get(x, y);
}
public A set(int x, A val) {
A old = Matrix.this.get(x, y);
Matrix.this.set(x, y, val);
return old;
}
};
}
}
static class Seconds implements Comparable , IFieldsToList{
double seconds;
Seconds() {}
Seconds(double seconds) {
this.seconds = seconds;}
public boolean equals(Object o) {
if (!(o instanceof Seconds)) return false;
Seconds __1 = (Seconds) o;
return seconds == __1.seconds;
}
public int hashCode() {
int h = -660217249;
h = boostHashCombine(h, _hashCode(seconds));
return h;
}
public Object[] _fieldsToList() { return new Object[] {seconds}; }
final double get(){ return seconds(); }
final double getDouble(){ return seconds(); }
double seconds() { return seconds; }
public String toString() { return formatDouble(seconds, 3) + " s"; }
public int compareTo(Seconds s) {
return cmp(seconds, s.seconds);
}
Seconds div(double x) { return new Seconds(get()/x); }
Seconds minus(Seconds x) { return new Seconds(get()-x.get()); }
}
static class RegisteredReference implements IRef {
Meta owner; // all we require is a meta field
A value;
RegisteredReference() {
//if (!dynamicObjectIsLoading()) registerRef();
}
/*void registerRef {
vmBus_send registeringReference(this);
}*/
// Note that the single-argument constructor takes an owner, not a value
RegisteredReference(Meta owner) {
this(owner, null);
}
RegisteredReference(Meta owner, A value) {
this.value = value;
this.owner = owner;
index();
//registerRef();
}
// get owning object (source)
Meta owner() { return owner; }
// get target
public A get() { return value; }
public boolean has() { return value != null; }
public boolean set_trueIfChanged(A a) {
if (eq(a, value)) return false;
unindex();
value = a;
index();
return true;
}
public void set(A a) {
set_trueIfChanged(a);
}
void setIfEmpty(A a) {
if (!has()) set(a);
}
public void set(IRef ref) { set(ref == null ? null : ref.get()); }
public void clear() { set((A) null); }
// can override
boolean validRef() { return true; }
// TODO: sync all the indexing and unindexing!?
void index() {
if (!validRef()) return;
var br = lookupInterface(IHasBackRefs.class, get());
{ if (br != null) br._registerBackRef(this); }
}
void unindex() {
if (!validRef()) return;
var br = lookupInterface(IHasBackRefs.class, get());
{ if (br != null) br._unregisterBackRef(this); }
}
// not used yet
void change() {}
public String toString() {
return
str(value);
}
}
abstract static class IntegerIterator {
abstract boolean hasNext();
abstract int next();
}
abstract static class RandomAccessAbstractList extends AbstractList implements RandomAccess {
}
static interface IHasBackRefs {
public void _registerBackRef(IRef ref);
public void _unregisterBackRef(IRef ref);
}
// could almost add IVar here - but void set() and bool set() are incompatible in some places
static interface IRef extends IF0 {
// called by the referencee to atomically replace itself
// Passing oldValue to avoid race conditions
public default void replaceValue(A oldValue, A newValue) {}
}
static Class> getClass(String name) {
return _getClass(name);
}
static Class getClass(Object o) {
return _getClass(o);
}
static Class getClass(Object realm, String name) {
return _getClass(realm, name);
}
static boolean classIsExportedTo(Class c, Module destModule) {
if (c == null || destModule == null) return false;
Module srcModule = c.getModule();
String packageName = c.getPackageName();
return srcModule.isExported(packageName, destModule);
}
static boolean isAbstract(Class c) {
return (c.getModifiers() & Modifier.ABSTRACT) != 0;
}
static boolean isAbstract(Method m) {
return (m.getModifiers() & Modifier.ABSTRACT) != 0;
}
static boolean reflection_isForbiddenMethod(Method m) {
return m.getDeclaringClass() == Object.class
&& eqOneOf(m.getName(), "finalize", "clone", "registerNatives");
}
static Set allInterfacesImplementedBy(Class c) {
if (c == null) return null;
HashSet set = new HashSet();
allInterfacesImplementedBy_find(c, set);
return set;
}
static void allInterfacesImplementedBy_find(Class c, Set set) {
if (c.isInterface() && !set.add(c)) return;
do {
for (Class intf : c.getInterfaces())
allInterfacesImplementedBy_find(intf, set);
} while ((c = c.getSuperclass()) != null);
}
static Method findMethod(Object o, String method, Object... args) {
return findMethod_cached(o, method, args);
}
static boolean findMethod_checkArgs(Method m, Object[] args, boolean debug) {
Class>[] types = m.getParameterTypes();
if (types.length != args.length) {
if (debug)
System.out.println("Bad parameter length: " + args.length + " vs " + types.length);
return false;
}
for (int i = 0; i < types.length; i++)
if (!(args[i] == null || isInstanceX(types[i], args[i]))) {
if (debug)
System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]);
return false;
}
return true;
}
static Method findStaticMethod(Class c, String method, Object... args) {
Class _c = c;
while (c != null) {
for (Method m : c.getDeclaredMethods()) {
if (!m.getName().equals(method))
continue;
if ((m.getModifiers() & Modifier.STATIC) == 0 || !findStaticMethod_checkArgs(m, args))
continue;
return m;
}
c = c.getSuperclass();
}
return null;
}
static boolean findStaticMethod_checkArgs(Method m, Object[] args) {
Class>[] types = m.getParameterTypes();
if (types.length != args.length)
return false;
for (int i = 0; i < types.length; i++)
if (!(args[i] == null || isInstanceX(types[i], args[i])))
return false;
return true;
}
static String unquote(String s) {
if (s == null) return null;
if (startsWith(s, '[')) {
int i = 1;
while (i < s.length() && s.charAt(i) == '=') ++i;
if (i < s.length() && s.charAt(i) == '[') {
String m = s.substring(1, i);
if (s.endsWith("]" + m + "]"))
return s.substring(i+1, s.length()-i-1);
}
}
if (s.length() > 1) {
char c = s.charAt(0);
if (c == '\"' || c == '\'') {
int l = endsWith(s, c) ? s.length()-1 : s.length();
StringBuilder sb = new StringBuilder(l-1);
for (int i = 1; i < l; i++) {
char ch = s.charAt(i);
if (ch == '\\') {
char nextChar = (i == l - 1) ? '\\' : s.charAt(i + 1);
// Octal escape?
if (nextChar >= '0' && nextChar <= '7') {
String code = "" + nextChar;
i++;
if ((i < l - 1) && s.charAt(i + 1) >= '0'
&& s.charAt(i + 1) <= '7') {
code += s.charAt(i + 1);
i++;
if ((i < l - 1) && s.charAt(i + 1) >= '0'
&& s.charAt(i + 1) <= '7') {
code += s.charAt(i + 1);
i++;
}
}
sb.append((char) Integer.parseInt(code, 8));
continue;
}
switch (nextChar) {
case '\"': ch = '\"'; break;
case '\\': ch = '\\'; break;
case 'b': ch = '\b'; break;
case 'f': ch = '\f'; break;
case 'n': ch = '\n'; break;
case 'r': ch = '\r'; break;
case 't': ch = '\t'; break;
case '\'': ch = '\''; break;
// Hex Unicode: u????
case 'u':
if (i >= l - 5) {
ch = 'u';
break;
}
int code = Integer.parseInt(
"" + s.charAt(i + 2) + s.charAt(i + 3)
+ s.charAt(i + 4) + s.charAt(i + 5), 16);
sb.append(Character.toChars(code));
i += 5;
continue;
default:
ch = nextChar; // added by Stefan
}
i++;
}
sb.append(ch);
}
return sb.toString();
}
}
return s; // not quoted - return original
}
static List quoteAll(String[] l) {
return quoteAll(asList(l));
}
static List quoteAll(Collection