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.*;
// grayscale, actually
import java.awt.image.DataBufferByte;
import static x30_pkg.x30_util.DynamicObject;
import java.awt.geom.*;
import java.text.*;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import java.nio.charset.Charset;
class main {
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(GrabbableRGBBytePixels gp) { grab(gp, new Decolorizer.Simple()); }
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
var gp = grabbableRGBBytePixels(image);
if (gp != null)
grab(gp, decolorizer);
else
grab(grabbableIntPixels_fastOrSlow(image), decolorizer);
}
}
void grab(GrabbableRGBBytePixels gp, Decolorizer decolorizer) {
if (decolorizer == null) decolorizer = new Decolorizer.Simple();
alloc(gp.w, gp.h);
int w = this.w, h = this.h;
// first row
int iImage = gp.offset, sum = 0, pixelStride = gp.pixelStride;
byte[] image = gp.data;
for (int x = 0; x < w; x++) {
int packed = rgbInt(image[iImage], image[iImage+1], image[iImage+2]);
iImage += pixelStride;
int brightness = decolorizer.toGrayScale(packed);
data[x] = (sum += brightness);
}
// subsequent rows
var ping = pingSource();
int scanlineExtra = gp.scanlineStride-w*pixelStride;
iImage = gp.offset+gp.scanlineStride;
int i = w;
for (int y = 1; y < h; y++) {
sum = 0;
for (int x = 0; x < w; x++) {
int packed = rgbInt(image[iImage], image[iImage+1], image[iImage+2]);
iImage += pixelStride;
int brightness = decolorizer.toGrayScale(packed);
sum += brightness;
data[i] = sum + data[i-w];
i++;
}
iImage += scanlineExtra;
{ if (ping != null) ping.get(); }
} // for y
}
void grab(GrabbableIntPixels gp, Decolorizer decolorizer) {
if (isDefaultDecolorizer(decolorizer))
{ 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 [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;
}
// get brightness of pixel
public int getInt(int x, int y) {
return iround(rectSum(x, y, x+1, y+1, 0));
}
// returns RGB pixel without alpha
public int getPixel(int x, int y) {
return rgbIntFromGrayscale(getInt(x, y));
}
public BufferedImage getBufferedImage() {
//ret scaleDownUsingIntegralImageBW(this, w).getBufferedImage();
Object src = metaGet("src", this);
if (src instanceof BufferedImage) return ((BufferedImage) src);
return grayImageFromIBWIntegralImage(this);
}
}
static BufferedImage loadImage2(String snippetIDOrURL) {
return loadBufferedImage(snippetIDOrURL);
}
static BufferedImage loadImage2(File file) {
return loadBufferedImage(file);
}
static BufferedImage toBufferedImage(Object o) {
return toBufferedImageOpt(o);
}
static Boolean grabbableGrayPixels_succeeded;
static Throwable grabbableGrayPixels_error;
static boolean grabbableGrayPixels_enable = true;
static GrabbableGrayPixels grabbableGrayPixels(BufferedImage img) {
if (img == null || !grabbableGrayPixels_enable) return null;
try {
var result = grabbableGrayPixels_impl(img);
grabbableGrayPixels_succeeded = result != null;
return result;
} catch (Throwable e) { grabbableGrayPixels_error = e;
grabbableGrayPixels_succeeded = false;
throw rethrow(e); }
}
static GrabbableGrayPixels grabbableGrayPixels_impl(BufferedImage img) {
Raster raster = img.getRaster();
SampleModel sampleModel = raster.getSampleModel();
if (!(sampleModel instanceof PixelInterleavedSampleModel)) return null;
DataBufferByte dataBuffer = (DataBufferByte) (raster.getDataBuffer());
assertEquals(1, dataBuffer.getNumBanks());
assertEquals(DataBuffer.TYPE_BYTE, dataBuffer.getDataType());
// Let's at this point assume the raster data is gray and not a palette
int w = img.getWidth(), h = img.getHeight();
int scanlineStride = ((PixelInterleavedSampleModel) sampleModel).getScanlineStride();
byte[] pixels = dataBuffer.getData();
int offset = dataBuffer.getOffset();
int translateX = raster.getSampleModelTranslateX();
int translateY = raster.getSampleModelTranslateY();
offset += -translateX-translateY*scanlineStride;
return new GrabbableGrayPixels(pixels, w, h, offset, scanlineStride);
}
static GrabbableRGBBytePixels grabbableRGBBytePixels(BufferedImage img) {
Raster raster = img.getRaster();
SampleModel _sampleModel = raster.getSampleModel();
if (!(_sampleModel instanceof PixelInterleavedSampleModel)) return null;
PixelInterleavedSampleModel sampleModel = (PixelInterleavedSampleModel) _sampleModel;
DataBufferByte dataBuffer = (DataBufferByte) (raster.getDataBuffer());
assertEquals(1, dataBuffer.getNumBanks());
assertEquals(DataBuffer.TYPE_BYTE, dataBuffer.getDataType());
// Let's at this point assume the raster data is what we
// think it is... (TODO: test on unusual platforms)
int w = img.getWidth(), h = img.getHeight();
int pixelStride = sampleModel.getPixelStride();
int scanlineStride = sampleModel.getScanlineStride();
byte[] pixels = dataBuffer.getData();
int offset = dataBuffer.getOffset();
int translateX = raster.getSampleModelTranslateX();
int translateY = raster.getSampleModelTranslateY();
offset += -translateX-translateY*scanlineStride;
return new GrabbableRGBBytePixels(pixels, w, h, offset, scanlineStride, pixelStride);
}
static GrabbableIntPixels grabbableIntPixels_fastOrSlow(BufferedImage image) { try {
try {
GrabbableIntPixels gp = grabbableIntPixels(image);
if (gp != null) return gp;
} catch (Throwable __e) { printStackTrace(__e); }
// Use pixelGrabber if quick method fails
int w = image.getWidth(), h = image.getHeight();
int[] data = new int[w*h];
PixelGrabber pixelGrabber = new PixelGrabber(image, 0, 0, w, h, data, 0, w);
if (!pixelGrabber.grabPixels())
throw fail("Could not grab pixels");
return new GrabbableIntPixels(data, w, h, 0, w);
} catch (Exception __e) { throw rethrow(__e); } }
static int rgbInt(int r, int g, int b) {
return (clamp(r, 0, 255) << 16) | (clamp(g, 0, 255) << 8) | clamp(b, 0, 255);
}
static int rgbInt(byte r, byte g, byte b) {
return (ubyteToInt(r) << 16) | (ubyteToInt(g) << 8) | ubyteToInt(b);
}
// assumptions:
// -pingSource() stays constant within a stack frame (so you can cache it)
// -all changes happen with tempSetPingSource
// -multiple threads can share a PingSource
static PingSource pingSource() {
return pingSource_tl().get();
}
static PingSource pingSource(Thread thread) {
return pingSource_tl().get(thread);
}
static boolean isDefaultDecolorizer(Decolorizer decolorizer) {
return decolorizer == null || decolorizer instanceof Decolorizer.Simple;
}
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 int min(int a, int b) {
return Math.min(a, b);
}
static long min(long a, long b) {
return Math.min(a, b);
}
static float min(float a, float b) { return Math.min(a, b); }
static float min(float a, float b, float c) { return min(min(a, b), c); }
static double min(double a, double b) {
return Math.min(a, b);
}
static double min(double[] c) {
double x = Double.MAX_VALUE;
for (double d : c) x = Math.min(x, d);
return x;
}
static float min(float[] c) {
float x = Float.MAX_VALUE;
for (float d : c) x = Math.min(x, d);
return x;
}
static byte min(byte[] c) {
byte x = 127;
for (byte d : c) if (d < x) x = d;
return x;
}
static short min(short[] c) {
short x = 0x7FFF;
for (short d : c) if (d < x) x = d;
return x;
}
static int min(int[] c) {
int x = Integer.MAX_VALUE;
for (int d : c) if (d < x) x = d;
return x;
}
static int ifloor(double d) {
return (int) Math.floor(d);
}
static IntRange ifloor(DoubleRange r) {
return r == null ? null : intRange(ifloor(r.start), ifloor(r.end));
}
static double blend2D(double val, double val2, double val3, double val4,
double xFrac, double yFrac) {
double upper = blend(val, val2, xFrac);
double lower = blend(val3, val4, xFrac);
return blend(upper, lower, yFrac);
}
// 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 double doubleRatio(double x, double y) {
return y == 0 ? 0 : x/y;
}
static double doubleRatio(Seconds x, Seconds y) {
return doubleRatio(x.get(), y.get());
}
static int bwIntegralImage_sumRect(BWIntegralImage img, int x1, int y1, int x2, int y2) {
int bottomLeft = img.getIIValue(x1-1, y2-1);
int bottomRight = img.getIIValue(x2-1, y2-1);
int topLeft = img.getIIValue(x1-1, y1-1);
int topRight = img.getIIValue(x2-1, y1-1);
return bottomRight+topLeft-topRight-bottomLeft;
}
static int bwIntegralImage_sumRect(IBWIntegralImage img, int x1, int y1, int x2, int y2) {
int bottomLeft = img.getIIValue(x1-1, y2-1);
int bottomRight = img.getIIValue(x2-1, y2-1);
int topLeft = img.getIIValue(x1-1, y1-1);
int topRight = img.getIIValue(x2-1, y1-1);
return bottomRight+topLeft-topRight-bottomLeft;
}
static double bwIntegralImage_sumRect(IBWIntegralImage img, double x1, double y1, double x2, double y2) {
double bottomLeft = img.getIIValue(x1-1, y2-1);
double bottomRight = img.getIIValue(x2-1, y2-1);
double topLeft = img.getIIValue(x1-1, y1-1);
double topRight = img.getIIValue(x2-1, y1-1);
return bottomRight+topLeft-topRight-bottomLeft;
}
static int iround(double d) {
return (int) Math.round(d);
}
static int iround(Number n) {
return iround(toDouble(n));
}
// brightness: 0 to 255
static int rgbIntFromGrayscale(int brightness) {
return brightness | (brightness << 8) | (brightness << 16);
}
static int getInt(List c, int i) {
return toInt(get(c, i));
}
static int getInt(Map map, Object key) {
return toInt(mapGet(map, key));
}
static int getInt(Object o, String field) {
return toInt(getOpt(o, (String) field));
}
static int getInt(String field, Object o) {
return getInt(o, field);
}
static Object metaGet(IMeta o, Object key) {
return metaMapGet(o, key);
}
static Object metaGet(Object o, Object key) {
return metaMapGet(o, key);
}
static Object metaGet(String key, IMeta o) {
return metaMapGet(o, key);
}
static Object metaGet(String key, Object o) {
return metaMapGet(o, key);
}
static BufferedImage grayImageFromIBWIntegralImage(IBWIntegralImage img) {
int w = img.getWidth(), h = img.getHeight();
byte[] pixels = new byte[w*h];
int i = 0;
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++) {
int pixel = img.getPixelBrightness(x, y);
pixels[i++] = clampToUByte(pixel);
}
return newGrayBufferedImage(w, h, pixels);
}
static boolean loadBufferedImage_useImageCache = true;
static BufferedImage loadBufferedImage(String snippetIDOrURLOrFile) { try {
ping();
if (snippetIDOrURLOrFile == null) return null;
if (isURL(snippetIDOrURLOrFile))
return imageIO_readURL(snippetIDOrURLOrFile);
if (isSnippetID(snippetIDOrURLOrFile)) {
String snippetID = "" + parseSnippetID(snippetIDOrURLOrFile);
IResourceLoader rl = vm_getResourceLoader();
if (rl != null)
return loadBufferedImage(rl.loadLibrary(snippetID));
File dir = imageSnippetsCacheDir();
if (loadBufferedImage_useImageCache) {
dir.mkdirs();
File file = new File(dir, snippetID + ".png");
if (file.exists() && file.length() != 0)
try {
return ImageIO.read(file);
} catch (Throwable e) {
e.printStackTrace();
// fall back to loading from sourceforge
}
}
String imageURL = snippetImageURL_http(snippetID);
print("Loading image: " + imageURL);
BufferedImage image = imageIO_readURL(imageURL);
if (loadBufferedImage_useImageCache) {
File tempFile = new File(dir, snippetID + ".tmp." + System.currentTimeMillis());
ImageIO.write(image, "png", tempFile);
tempFile.renameTo(new File(dir, snippetID + ".png"));
//Log.info("Cached image.");
}
//Log.info("Loaded image.");
return image;
} else
return loadBufferedImage(new File(snippetIDOrURLOrFile));
} catch (Exception __e) { throw rethrow(__e); } }
static BufferedImage loadBufferedImage(File file) {
return loadBufferedImageFile(file);
}
static BufferedImage toBufferedImageOpt(Object o) {
if (o instanceof BufferedImage) return ((BufferedImage) o);
if (o instanceof Image) return copyImage((Image) o);
if (o instanceof MakesBufferedImage)
return ((MakesBufferedImage) o).getBufferedImage();
String c = getClassName(o);
// Keep this because it also works on imported objects
if (eqOneOf(c, "main$BWImage", "main$RGBImage"))
return (BufferedImage) call(o, "getBufferedImage");
return null;
}
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 A assertEquals(Object x, A y) {
return assertEquals("", x, y);
}
static A assertEquals(String msg, Object x, A y) {
if (assertVerbose()) return assertEqualsVerbose(msg, x, y);
if (!(x == null ? y == null : x.equals(y)))
throw fail((msg != null ? msg + ": " : "") + y + " != " + x);
return y;
}
static Boolean grabbableIntPixels_succeeded;
static boolean grabbableIntPixels_enable = true;
static GrabbableIntPixels grabbableIntPixels(BufferedImage img) {
if (img == null || !grabbableIntPixels_enable) return null;
try {
var result = grabbableIntPixels_impl(img);
grabbableIntPixels_succeeded = result != null;
return result;
} catch (Throwable _e) {
grabbableIntPixels_succeeded = false;
throw rethrow(_e); }
}
static GrabbableIntPixels grabbableIntPixels_impl(BufferedImage img) {
Raster raster = img.getRaster();
SampleModel _sampleModel = raster.getSampleModel();
if (!(_sampleModel instanceof SinglePixelPackedSampleModel)) return null;
SinglePixelPackedSampleModel sampleModel = (SinglePixelPackedSampleModel) _sampleModel;
DataBufferInt dataBuffer = (DataBufferInt) (raster.getDataBuffer());
assertEquals(1, dataBuffer.getNumBanks());
assertEquals(DataBuffer.TYPE_INT, dataBuffer.getDataType());
// Let's at this point assume the raster data is what we
// think it is... (TODO: test on unusual platforms)
int w = img.getWidth(), h = img.getHeight();
int scanlineStride = sampleModel.getScanlineStride();
int[] pixels = dataBuffer.getData();
int offset = dataBuffer.getOffset();
int translateX = raster.getSampleModelTranslateX();
int translateY = raster.getSampleModelTranslateY();
offset += -translateX-translateY*scanlineStride;
return new GrabbableIntPixels(pixels, w, h, offset, scanlineStride);
}
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 float clamp(float x, float a, float b) {
return x < a ? a : x > b ? b : x;
}
static double clamp(double x, double a, double b) {
return x < a ? a : x > b ? b : x;
}
static int clamp(int x, int a, int b) {
return x < a ? a : x > b ? b : x;
}
static long clamp(long x, long a, long b) {
return x < a ? a : x > b ? b : x;
}
static int ubyteToInt(byte b) {
return b & 0x0FF;
}
static int ubyteToInt(char c) {
return c & 0x0FF;
}
static BetterThreadLocal pingSource_tl_var = new BetterThreadLocal() {
@Override
public PingSource initialValue() {
return ping_v3_pingSourceMaker().get();
}
};
static BetterThreadLocal pingSource_tl() {
return pingSource_tl_var;
}
static RuntimeException asRuntimeException(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static IntRange intRange(int start, int end) {
return new IntRange(start, end);
}
static int blend(int x, int y, double yish) {
double xish = 1-yish;
return (int) (x*xish+y*yish);
}
static double blend(double x, double y, double yish) {
double xish = 1-yish;
return x*xish+y*yish;
}
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(IMultiMap mm) { return mm == null ? 0 : mm.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(AppendableChain a) { return a == null ? 0 : a.size; }
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 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 Object getOptDynOnly(DynamicObject o, String field) {
if (o == null || o.fieldValues == null) return null;
return o.fieldValues.get(field);
}
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 int toInt(Object o) {
if (o == null) return 0;
if (o instanceof Number)
return ((Number) o).intValue();
if (o instanceof String)
return parseInt((String) o);
if (o instanceof Boolean)
return boolToInt((Boolean) o);
throw fail("woot not int: " + getClassName(o));
}
static int toInt(long l) {
if (l != (int) l) throw fail("Too large for int: " + l);
return (int) l;
}
static B mapGet(Map map, A a) {
return map == null || a == null ? null : map.get(a);
}
static B mapGet(A a, Map map) {
return map == null || a == null ? null : map.get(a);
}
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 Object metaMapGet(IMeta o, Object key) {
return o == null ? null : o.metaGet(key); // We now let the object itself do it (overridable!)
}
static Object metaMapGet(Object o, Object key) {
return metaMapGet(toIMeta(o), key);
}
static byte clampToUByte(long l) {
return (byte) clamp(l, 0, 255);
}
// undefined color, seems to be all black in practice
static BufferedImage newGrayBufferedImage(int w, int h) {
return new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
}
static BufferedImage newGrayBufferedImage(int w, int h, byte[] pixels) {
return byteArrayToGrayBufferedImage(pixels, w, h);
}
// legacy mode
//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();
// ignore pingSource if not PingV3
static boolean ping(PingSource pingSource) { return ping(); }
// 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 boolean isURL(String s) {
return startsWithOneOf(s, "http://", "https://", "file:");
}
static BufferedImage imageIO_readURL(String url) { try {
return ImageIO.read(new URL(url));
} catch (Exception __e) { throw rethrow(__e); } }
public static boolean isSnippetID(String s) {
try {
parseSnippetID(s);
return true;
} catch (RuntimeException e) {
return false;
}
}
public static long parseSnippetID(String snippetID) {
long id = Long.parseLong(shortenSnippetID(snippetID));
if (id == 0) throw fail("0 is not a snippet ID");
return id;
}
static IResourceLoader vm_getResourceLoader() {
return proxy(IResourceLoader.class, vm_generalMap_get("_officialResourceLoader"));
}
static File imageSnippetsCacheDir() {
return javaxCachesDir("Image-Snippets");
}
static String snippetImageURL_http(String snippetID) {
return snippetImageURL_http(snippetID, "png");
}
static String snippetImageURL_http(String snippetID, String contentType) {
return replacePrefix("https://", "http://", snippetImageURL(snippetID, contentType)).replace(":8443", ":8080");
}
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